diff --git a/.claude/skills/uts-to-kotlin/SKILL.md b/.claude/skills/uts-to-kotlin/SKILL.md index ed8fe752a..f7f5368b8 100644 --- a/.claude/skills/uts-to-kotlin/SKILL.md +++ b/.claude/skills/uts-to-kotlin/SKILL.md @@ -676,13 +676,12 @@ Recognise a **proxy** spec by a reference to `create_proxy_session()`, proxy `ru A **direct-sandbox** spec (no `create_proxy_session`, no rules — just happy-path interop against `nonprod:sandbox`) uses the same `SandboxApp` provisioning and the same `runTest` / `@BeforeAll`+`runBlocking` lifecycle as a proxy test, but **drops all proxy wiring**: no `ProxyManager.ensureProxy()`, no `ProxySession`, no `connectThroughProxy`. The client connects straight to the sandbox host. `ChannelHistoryTest` (realtime) and `ObjectsLifecycleTest` (liveobjects) are the reference examples — read one before translating a direct-sandbox spec. -**Client wiring** — point both transports at the sandbox host (explicit hosts auto-disable fallback hosts, so no `fallbackHosts`): +**Client wiring** — point the client at the sandbox endpoint: ```kotlin private fun newClient(useBinaryProtocol: Boolean): AblyRealtime = TestRealtimeClient { key = app.defaultKey - realtimeHost = SandboxApp.sandboxHost // sandbox.realtime.ably-nonprod.net - restHost = SandboxApp.sandboxHost + endpoint = SandboxApp.sandboxEndpoint // nonprod:sandbox this.useBinaryProtocol = useBinaryProtocol autoConnect = false } @@ -717,7 +716,7 @@ Import `org.junit.jupiter.params.ParameterizedTest` and `org.junit.jupiter.param | Pseudocode | Kotlin | |---|---| | `AWAIT channel.attach()` | `channel.attach()` then `awaitChannelState(channel, ChannelState.attached, 10.seconds)` | -| `AWAIT channel.publish(name, data)` (await the ack) | wrap the **non-deprecated** `publish(name, data, Callback)` overload in `suspendCancellableCoroutine` — resume on `onSuccess`, fail on `onError` (the `CompletionListener` overload is deprecated) | +| `AWAIT channel.publish(name, data)` (await the ack) | wrap the `publish(name, data, Callback)` overload in `suspendCancellableCoroutine` — resume on `onSuccess`, fail on `onError` | | `poll_until(() => AWAIT channel.history().items.length == N, …)` | `pollUntil(10.seconds, 500.milliseconds) { channel.history(null).items().size == N }` (`history()` is a blocking REST call; `null` = no params) | Use generous timeouts (10–30s) — real network is involved. Everything else is the shared foundation described at the top of this section; a direct-sandbox test just skips the proxy-only subsections (`ProxySession`, rule factories, the event log). @@ -728,7 +727,7 @@ Three helpers live under `uts/src/main/kotlin/io/ably/lib/uts/infra/integration/ - **`ProxyManager`** (`infra/integration/proxy/ProxyManager.kt`, package `io.ably.lib.uts.infra.integration.proxy`) — downloads/starts the shared `uts-proxy` process. Call `ProxyManager.ensureProxy()` once per suite in setup. - **`ProxySession`** (`infra/integration/proxy/ProxySession.kt`, same package) — one programmable session wrapping the proxy control API; also defines the `connectThroughProxy` extension and the rule-builder helpers. -- **`SandboxApp`** (`infra/integration/SandboxApp.kt`, package `io.ably.lib.uts.infra.integration`) — provisions/deletes a sandbox test app from the shared `test-app-setup.json` in ably-common. `SandboxApp.create()` returns a `SandboxApp` with `appId`, `defaultKey`, and `keys` (`defaultKey` is a full-capability `appId.keyId:keySecret`); `app.delete()` tears it down. Provision in suite setup, delete in teardown. Also owns the single upstream sandbox host constant `SandboxApp.sandboxHost` (`sandbox.realtime.ably-nonprod.net`, the resolved `nonprod:sandbox` endpoint) — the default target of every `ProxySession` (both `realtimeHost` and `restHost`), and what direct-sandbox clients set `realtimeHost` / `restHost` from. +- **`SandboxApp`** (`infra/integration/SandboxApp.kt`, package `io.ably.lib.uts.infra.integration`) — provisions/deletes a sandbox test app from the shared `test-app-setup.json` in ably-common. `SandboxApp.create()` returns a `SandboxApp` with `appId`, `defaultKey`, and `keys` (`defaultKey` is a full-capability `appId.keyId:keySecret`); `app.delete()` tears it down. Provision in suite setup, delete in teardown. Also owns `SandboxApp.sandboxEndpoint` (`nonprod:sandbox`), which direct-sandbox clients set as their `endpoint`, and `SandboxApp.sandboxHost` (`sandbox.realtime.ably-nonprod.net`, the hostname that endpoint resolves to) — the default upstream target of every `ProxySession`. Import what the tier needs: a **direct-sandbox** test imports `io.ably.lib.uts.infra.integration.SandboxApp` plus `io.ably.lib.uts.infra.unit.TestRealtimeClient` and `io.ably.lib.uts.infra.{awaitState, pollUntil}`; a **proxy** test additionally imports `io.ably.lib.uts.infra.integration.proxy.{ProxyManager, ProxySession, connectThroughProxy}`. @@ -799,11 +798,11 @@ val client = TestRealtimeClient { } ``` -ably-java has **no `endpoint` ClientOptions field**; `connectThroughProxy` sets the discrete host fields for you: +`connectThroughProxy` sets the proxy-def options for you: | Proxy-def option | What `connectThroughProxy` sets | |---|---| -| `endpoint: "localhost"` | `realtimeHost` **and** `restHost` = `session.proxyHost` (`"localhost"`) | +| `endpoint: "localhost"` | `endpoint = session.proxyHost` (`"localhost"`) | | `port: proxy_port` | `port = session.proxyPort` | | `tls: false` | `tls = false` | | `useBinaryProtocol: false` | already the `ClientOptionsBuilder` default — left untouched | diff --git a/.claude/skills/uts-to-kotlin/references/objects-mapping.md b/.claude/skills/uts-to-kotlin/references/objects-mapping.md index 26ab9b755..c97b2a8f9 100644 --- a/.claude/skills/uts-to-kotlin/references/objects-mapping.md +++ b/.claude/skills/uts-to-kotlin/references/objects-mapping.md @@ -623,10 +623,9 @@ REST provisioning" convention survives even though the module's internals are vi > envelope on the legacy `sandbox-rest.ably.io` host; both were aligned upstream — to this V2 shape and to > the canonical nonprod sandbox host `sandbox.realtime.ably-nonprod.net` — in ably/specification#497. > -> **Sandbox host.** `provisionObjectsViaRest` sets `restHost = SandboxApp.sandboxHost` -> (`sandbox.realtime.ably-nonprod.net`) — the same nonprod host `SandboxApp` and the realtime clients use, -> **not** `environment="sandbox"` (which resolves to the legacy `sandbox-rest.ably.io`, and -> can't be combined with `restHost` per `Hosts.java` TO3k2/TO3k3). The REST call hits the live sandbox +> **Sandbox host.** `provisionObjectsViaRest` sets `endpoint = SandboxApp.sandboxEndpoint` +> (`nonprod:sandbox`, resolving to `sandbox.realtime.ably-nonprod.net`) — the same endpoint `SandboxApp` +> and the realtime clients use. The REST call hits the live sandbox > today, and the realtime client observes the provisioned data through the SDK's OBJECT_SYNC + > `RealtimeObject.get()` (both implemented). diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index 36fb02df5..7c8e819ab 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -23,4 +23,31 @@ jobs: distribution: 'temurin' - name: Set up Gradle uses: gradle/actions/setup-gradle@d9c87d481d55275bb5441eef3fe0e46805f9ef70 # v3 - - run: ./gradlew checkWithCodenarc checkstyleMain checkstyleTest runUnitTests runLiveObjectsUnitTests :java:runUtsUnitTests :uts:runUtsUnitTests + - run: ./gradlew checkWithCodenarc checkstyleMain checkstyleTest runUnitTests runLiveObjectsUnitTests :core:runUtsUnitTests :uts:runUtsUnitTests + + # A second UTS leg through the server door's builders (see the uts.side handling in + # uts/.../ClientFactories.kt): the builders stamp a side-declaring agent entry and pass + # everything else through, so conformance must be identical on both legs; SideModesTest + # fails a leg whose stamp does not match. There is no device leg on the JVM — the device + # door is an Android artifact, covered by the instrumentation tests in emulate.yml. + - run: ./gradlew :uts:runUtsUnitTests -Duts.side=server + + # Continuously proves the release pre-flight and that every published module + # builds a publishable artifact set, so version/coordinate regressions surface + # on PRs rather than on release day. + release-dry-run: + runs-on: ubuntu-latest + permissions: + contents: read + steps: + - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3 + with: + persist-credentials: false + - name: Set up the JDK + uses: actions/setup-java@17f84c3641ba7b8f6deff6309fc4c864478f5d62 # v3 + with: + java-version: '17' + distribution: 'temurin' + - name: Set up Gradle + uses: gradle/actions/setup-gradle@d9c87d481d55275bb5441eef3fe0e46805f9ef70 # v3 + - run: ./gradlew verifyReleaseArtifacts publishToMavenLocal diff --git a/.github/workflows/emulate.yml b/.github/workflows/emulate.yml index a95d1386c..c7bfe302f 100644 --- a/.github/workflows/emulate.yml +++ b/.github/workflows/emulate.yml @@ -14,7 +14,7 @@ jobs: strategy: fail-fast: false matrix: - android-api-level: [ 21, 24, 29, 35 ] + android-api-level: [ 24, 29, 35 ] steps: - name: checkout @@ -50,10 +50,10 @@ jobs: arch: ${{ steps.get-avd-arch.outputs.arch }} target: default # Print emulator logs if tests fail - script: ./gradlew :android:connectedAndroidTest ${{ matrix.android-api-level == 19 && '-PhttpURLConnection' || '' }} || (adb logcat -d System.out:I && exit 1) + script: ./gradlew :core-android:connectedAndroidTest :device:connectedAndroidTest ${{ matrix.android-api-level == 19 && '-PhttpURLConnection' || '' }} || (adb logcat -d System.out:I && exit 1) - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 if: always() with: - name: android-build-reports-${{ matrix.android-api-level }} - path: android/build/reports/ + name: core-android-build-reports-${{ matrix.android-api-level }} + path: core-android/build/reports/ diff --git a/.github/workflows/integration-test.yml b/.github/workflows/integration-test.yml index bbe3a5423..348bbe0f3 100644 --- a/.github/workflows/integration-test.yml +++ b/.github/workflows/integration-test.yml @@ -27,13 +27,13 @@ jobs: - name: Set up Gradle uses: gradle/actions/setup-gradle@d9c87d481d55275bb5441eef3fe0e46805f9ef70 # v3 - - run: ./gradlew :java:testRestSuite -PhttpURLConnection + - run: ./gradlew :core:testHttpSuite -PhttpURLConnection - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 if: always() with: - name: java-build-reports-rest - path: java/build/reports/ + name: core-build-reports-rest + path: core/build/reports/ check-realtime-httpurlconnection: runs-on: ubuntu-latest @@ -54,13 +54,13 @@ jobs: - name: Set up Gradle uses: gradle/actions/setup-gradle@d9c87d481d55275bb5441eef3fe0e46805f9ef70 # v3 - - run: ./gradlew :java:testRealtimeSuite -PhttpURLConnection + - run: ./gradlew :core:testRealtimeSuite -PhttpURLConnection - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 if: always() with: - name: java-build-reports-realtime - path: java/build/reports/ + name: core-build-reports-realtime + path: core/build/reports/ check-rest-okhttp: runs-on: ubuntu-latest permissions: @@ -80,7 +80,7 @@ jobs: - name: Set up Gradle uses: gradle/actions/setup-gradle@d9c87d481d55275bb5441eef3fe0e46805f9ef70 # v3 - - run: ./gradlew :java:testRestSuite + - run: ./gradlew :core:testHttpSuite check-realtime-okhttp: runs-on: ubuntu-latest @@ -101,7 +101,7 @@ jobs: - name: Set up Gradle uses: gradle/actions/setup-gradle@d9c87d481d55275bb5441eef3fe0e46805f9ef70 # v3 - - run: ./gradlew :java:testRealtimeSuite + - run: ./gradlew :core:testRealtimeSuite check-liveobjects: runs-on: ubuntu-latest @@ -143,4 +143,8 @@ jobs: - name: Set up Gradle uses: gradle/actions/setup-gradle@d9c87d481d55275bb5441eef3fe0e46805f9ef70 # v3 - - run: ./gradlew :java:runUtsIntegrationTests :uts:runUtsIntegrationTests + - run: ./gradlew :core:runUtsIntegrationTests :uts:runUtsIntegrationTests + + # A second leg through the server door's builders — see the uts.side handling in + # uts/.../ClientFactories.kt and the matching leg in check.yml. + - run: ./gradlew :uts:runUtsIntegrationTests -Duts.side=server diff --git a/.github/workflows/javadoc.yml b/.github/workflows/javadoc.yml index bef474bed..bf166f6e8 100644 --- a/.github/workflows/javadoc.yml +++ b/.github/workflows/javadoc.yml @@ -39,6 +39,6 @@ jobs: - name: Upload Documentation uses: ably/sdk-upload-action@4e694297f208b72b5a9f6b1248a1556f19f821d6 # v2 with: - sourcePath: java/build/docs/javadoc + sourcePath: core/build/docs/javadoc githubToken: ${{ secrets.GITHUB_TOKEN }} artifactName: javadoc diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 1eedbffe0..8094fe45f 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -46,6 +46,12 @@ jobs: - name: Set up Gradle uses: gradle/actions/setup-gradle@d9c87d481d55275bb5441eef3fe0e46805f9ef70 # v3 + # Fails before anything is uploaded if the artifact set, group or lockstep + # version drifts (core, core-android, device and server release + # together on the same version; partial release must be impossible). + - name: Release pre-flight + run: ./gradlew verifyReleaseArtifacts + - name: Publish and release to Maven Central run: ./gradlew publishAndReleaseToMavenCentral env: diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 76259f238..d873e68f2 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -5,13 +5,13 @@ 1. Fork it 2. Create your feature branch (`git checkout -b my-new-feature`) 3. Commit your changes (`git commit -am 'Add some feature'`) -4. Ensure you have added suitable tests and the test suite is passing(`./gradlew java:testRestSuite java:testRealtimeSuite android:connectedAndroidTest`) +4. Ensure you have added suitable tests and the test suite is passing(`./gradlew core:testHttpSuite core:testRealtimeSuite core-android:connectedAndroidTest`) 5. Push to the branch (`git push origin my-new-feature`) 6. Create a new Pull Request ### Building -The library consists of JRE-specific library (in `java/`) and an Android-specific library (in `android/`). The libraries are largely common-sourced; the `lib/` directory contains the common parts. +The library consists of JRE-specific library (in `core/`) and an Android-specific library (in `core-android/`). The libraries are largely common-sourced; the `lib/` directory contains the common parts. A gradle wrapper is included so these tasks can run without any prior installation of gradle. The Linux/OSX form of the commands, given below, is: @@ -23,11 +23,11 @@ but on Windows there is a batch file: The JRE-specific library JAR is built with: - ./gradlew java:jar + ./gradlew core:jar The Android-specific library AAR is built with: - ./gradlew android:assemble + ./gradlew core-android:assemble (The `ANDROID_HOME` environment variable must be set appropriately.) @@ -85,7 +85,7 @@ Once done, your custom network engine will be available for use within `ably-jav We use [Checkstyle](https://checkstyle.org/) to enforce code style and spot for transgressions and illogical constructs in our Java source files. -The Gradle build has been configured to run these on `java:assembleRelease`. +The Gradle build has been configured to run these on `core:assembleRelease`. It does not run for the Android build yet. You can run just the Checkstyle rules on their own using: @@ -123,53 +123,53 @@ The gradle project files can be imported to create projects in IntelliJ IDEA, Ec #### Importing into IntelliJ -The top-level ably-java project can be imported into IntelliJ IDEA, enabling development of both the java and android projects. This has been tested with IntelliJ IDEA Ultimate 2017.2. To import into IDEA: +The top-level ably-java project can be imported into IntelliJ IDEA, enabling development of both the core and core-android projects. This has been tested with IntelliJ IDEA Ultimate 2017.2. To import into IDEA: - do File->New->Project from Existing Sources... - select ably-pubsub-java/settings.gradle - in the import dialog, check "Use auto-import" and uncheck "Create separate module per source set" - select "ok" -This will create a project with separate java and android modules. +This will create a project with separate core and core-android modules. Interactive run/debug configurations to execute the unit tests can be created as follows: - select Run->Edit configurations ... -- for the java project, create a new "JUnit" run configuration; or for the android project create a new "Android Instrumented Tests" configuration; -- select the Class as RealtimeSuite or RestSuite; +- for the core project, create a new "JUnit" run configuration; or for the core-android project create a new "Android Instrumented Tests" configuration; +- select the Class as RealtimeSuite or HttpSuite; - select the relevant module for the classpath. In order to run the Android configuration it is necessary to set up the Android SDK path by selecting a project of module and opening the module settings. The Android SDK needs to be added under Platform Settings->SDKs. #### Importing into Eclipse -The top-level ably-java project can be imported into Eclipse, enabling development of the java project only. The Eclipse Android development plugin (ADT) is no longer supported. This has been tested with Eclipse Oxygen.2 +The top-level ably-java project can be imported into Eclipse, enabling development of the core project only. The Eclipse Android development plugin (ADT) is no longer supported. This has been tested with Eclipse Oxygen.2 To import into Eclipse: - do File->Import->Gradle->Existing Gradle project; - follow the wizard steps, selecting the ably-java root directory. -This will create two projects in the workspace; one for the top-level ably-java project, and one for the java project. +This will create two projects in the workspace; one for the top-level ably-java project, and one for the core project. -Interactive run/debug configurations for the java project can be created as follows: +Interactive run/debug configurations for the core project can be created as follows: - select Run->Run configurations ... - create a new JUnit configuration -- select the java project; -- select the Class as RealtimeSuite or RestSuite; +- select the core project; +- select the Class as RealtimeSuite or HttpSuite; - select JUnit 4 as the test runner. #### Importing into Android studio -Android studio does not include the components required to support development of the java project, it is not capable of importing the multi-level ably-java gradle project. It is possible to import the android project as a standalone project into Android Studio by deleting the top-level settings.gradle file, which effectively decouples the android and java projects. +Android studio does not include the components required to support development of the core project, it is not capable of importing the multi-level ably-java gradle project. It is possible to import the core-android project as a standalone project into Android Studio by deleting the top-level settings.gradle file, which effectively decouples the core-android and core projects. This has been tested with Android Studio 3.0.1. To import into Android Studio: - do Import project (Gradle, Eclipse ADT, etc); -- select ably-pubsub-java/android/build.gradle; +- select ably-pubsub-java/core-android/build.gradle; - select OK to Gradle Sync. -This creates a single android project and module. +This creates a single core-android project and module. Configuration of Run/Debug configurations for running the unit tests on Android is the same as for IntelliJ IDEA (above). @@ -183,28 +183,28 @@ but on Windows there is a batch file: gradlew.bat -Tests are based on JUnit, and there are separate suites for the REST and Realtime libraries, with gradle tasks +Tests are based on JUnit, and there are separate suites for the HTTP and Realtime libraries, with gradle tasks for the JRE-specific library: - ./gradlew java:testRestSuite + ./gradlew core:testHttpSuite - ./gradlew java:testRealtimeSuite + ./gradlew core:testRealtimeSuite -To run tests against a specific host, specify in the environment: +To run tests against a specific endpoint, specify it in the environment: - env ABLY_ENV=staging ./gradlew testRealtimeSuite + env ABLY_ENDPOINT=nonprod:staging ./gradlew testRealtimeSuite -Tests will run against the sandbox environment by default. +Tests will run against the `nonprod:sandbox` endpoint by default. Tests can be run on the Android-specific library. An Android device must be connected, either a real device or the Android emulator. - ./gradlew android:connectedAndroidTest + ./gradlew core-android:connectedAndroidTest We also have a small, fledgling set of unit tests which do not communicate with Ably's servers. The plan is to expand this collection of tests in due course: - ./gradlew java:runUnitTests + ./gradlew core:runUnitTests ### Interactive push tests @@ -225,7 +225,7 @@ signing.keyId=XXXXXXXX signing.password=ably-debug-key signing.secretKeyRingFile=/Users/username/.ably/ably-java-secring.gpg ``` -- Run `./gradlew android:assembleRelease` or `./gradlew android:assembleDebug`. +- Run `./gradlew core-android:assembleRelease` or `./gradlew core-android:assembleDebug`. ## Using `ably-java` / `ably-android` locally in other projects @@ -262,7 +262,7 @@ This library uses [semantic versioning](http://semver.org/). For each release, t If you've not configured the signing key in your [Gradle properties](https://docs.gradle.org/current/userguide/build_environment.html#sec:gradle_configuration_properties) then release builds will complain: - Cannot perform signing task ':java:signArchives' because it has no configured signatory + Cannot perform signing task ':core:signArchives' because it has no configured signatory You need to [configure Signatory credentials](https://docs.gradle.org/current/userguide/signing_plugin.html#sec:signatory_credentials), for example via the `gradle.properties` file in your `GRADLE_USER_HOME` folder (usually `~/.gradle`). diff --git a/README.md b/README.md index e22c6dbb5..8e44c8ee2 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,23 @@ Find out more: --- +> [!NOTE] +> **This branch carries the in-development 2.0 device/server package split.** The SDK is being +> restructured into new artifacts that declare which side of the network they run on, so that +> traffic classifies correctly on MAU-priced accounts: +> +> | Artifact | For | Entry point | +> |----------|-----|-------------| +> | `io.ably.pubsub:device` (aar) | Devices: Android apps and other end-user runtimes | `PubSubDevice.clientBuilder(...)` | +> | `io.ably.pubsub:server` (jar) | Servers and other trusted backend environments | `PubSubServer.httpClientBuilder(...)` / `PubSubServer.realtimeClientBuilder(...)` | +> | `io.ably.pubsub:core`, `io.ably.pubsub:core-android` | Internal implementation artifacts — do not depend on these directly | — | +> +> Nothing from this branch is published yet. The `io.ably:ably-java` and `io.ably:ably-android` +> 1.x artifacts continue to work and will receive security and critical fixes from a maintenance +> branch for one year after the 2.0 release. The installation instructions below still describe 1.x. + +--- + ## Getting started Everything you need to get started with Ably: @@ -65,13 +82,18 @@ implementation 'org.slf4j:slf4j-simple:2.0.7' Run the following to instantiate a client: ```java -import io.ably.lib.realtime.AblyRealtime; -import io.ably.lib.types.ClientOptions; +import io.ably.pubsub.realtime.PubSubRealtimeClient; +import io.ably.pubsub.server.PubSubServer; -ClientOptions options = new ClientOptions(apiKey); -AblyRealtime realtime = new AblyRealtime(options); +PubSubRealtimeClient realtime = PubSubServer.realtimeClientBuilder() + .key(apiKey) + .build(); ``` +On an end-user device, depend on `io.ably.pubsub:device` and build through +`PubSubDevice.clientBuilder()` instead; the builder you call declares which side of the +connection your code runs on. + --- ## Usage @@ -81,9 +103,10 @@ The following code connects to Ably's realtime messaging service, subscribes to ```java // Initialize Ably Realtime client -ClientOptions options = new ClientOptions("your-ably-api-key"); -options.clientId = "me"; -AblyRealtime realtimeClient = new AblyRealtime(options); +PubSubRealtimeClient realtimeClient = PubSubServer.realtimeClientBuilder() + .key("your-ably-api-key") + .clientId("me") + .build(); // Wait for connection to be established realtimeClient.connection.on(ConnectionEvent.connected, connectionStateChange -> { @@ -141,12 +164,12 @@ Enable proxy support by specifying proxy settings in the ClientOptions when init The following example sets up a proxy using the Pub/Sub Java SDK: ```java -import io.ably.lib.realtime.AblyRealtime; -import io.ably.lib.rest.AblyRest; -import io.ably.lib.transport.Defaults; -import io.ably.lib.types.ClientOptions; -import io.ably.lib.types.ProxyOptions; -import io.ably.lib.http.HttpAuth; +import io.ably.pubsub.realtime.PubSubRealtimeClient; +import io.ably.pubsub.transport.Defaults; +import io.ably.pubsub.types.ClientOptions; +import io.ably.pubsub.types.ProxyOptions; +import io.ably.pubsub.http.HttpAuth; +import io.ably.pubsub.http.PubSubHttpClient; public class AblyWithProxy { public static void main(String[] args) throws Exception { @@ -163,14 +186,17 @@ public class AblyWithProxy { proxy.password = "your-password"; // Replace with proxy password proxy.prefAuthType = HttpAuth.Type.BASIC; // Choose your preferred authentication type (e.g., BASIC or DIGEST) - // Attach the proxy settings to the client options - options.proxy = proxy; - - // Create an instance of Ably using the configured options - AblyRest ably = new AblyRest(options); + // Create an instance of Ably with the proxy settings attached + PubSubHttpClient ably = PubSubServer.httpClientBuilder() + .key("your-ably-api-key") + .proxy(proxy) + .build(); // Alternatively, for real-time connections - AblyRealtime ablyRealtime = new AblyRealtime(options); + PubSubRealtimeClient realtimeClient = PubSubServer.realtimeClientBuilder() + .key("your-ably-api-key") + .proxy(proxy) + .build(); // Use the Ably client as usual } diff --git a/UPGRADING.md b/UPGRADING.md new file mode 100644 index 000000000..88d0ee8c3 --- /dev/null +++ b/UPGRADING.md @@ -0,0 +1,201 @@ +# Upgrading from 1.x to 2.0 + +2.0 splits the SDK into one artifact per side of the connection: your code now declares whether it +runs on an end-user device or on infrastructure you control. + +| 1.x | 2.0 | +|-----|-----| +| `io.ably:ably-java` | `io.ably.pubsub:server` (backend) or `io.ably.pubsub:device` (end-user runtime) | +| `io.ably:ably-android` | `io.ably.pubsub:device` | +| `new AblyRealtime(options)` | `PubSubServer.realtimeClientBuilder()…build()` or `PubSubDevice.clientBuilder()…build()` | +| `new AblyRest(options)` | `PubSubServer.httpClientBuilder()…build()` | +| `io.ably.lib.*` | `io.ably.pubsub.*` | +| `io.ably.lib.rest.*` | `io.ably.pubsub.http.*` | +| `AblyRealtime`, `AblyRest` | `PubSubRealtimeClient`, `PubSubHttpClient` | + +## 1. Choose the artifact for your side + +| Artifact | For | Entry point | +|----------|-----|-------------| +| `io.ably.pubsub:device` | Android apps and other end-user runtimes | `PubSubDevice.clientBuilder(…)` | +| `io.ably.pubsub:server` | Servers and other trusted backend environments | `PubSubServer.realtimeClientBuilder(…)`, `PubSubServer.httpClientBuilder(…)` | + +Pick by where the code runs, not by which client you want: both doors give you a realtime client, +and connectionless operations (history, presence queries, token requests, `request()`, +`batchPublish()`) are available on it either way. + +Gradle: + +```gradle +// Backend / trusted server environment (JVM) +implementation 'io.ably.pubsub:server:2.0.0' + +// End-user device (Android app, or a JVM desktop client) +implementation 'io.ably.pubsub:device:2.0.0' +``` + +`device` is a Kotlin Multiplatform artifact, published as `device` (which Gradle resolves to the +right variant) plus `device-android` and `device-jvm`. Maven cannot resolve Gradle variants, so a +Maven consumer names `device-jvm` directly. + +**Android minimum API level.** `io.ably.pubsub:device` requires **API 24**. 1.x `io.ably:ably-android` +supported API 19, so an app that still targets 19–23 cannot move to the device artifact yet; stay on +1.x for now and open an issue so we can weigh the floor. + +The remaining published artifacts change group only, and all release in lockstep at the same version: +`io.ably:liveobjects` → `io.ably.pubsub:liveobjects`, and likewise `network-client-core`, +`network-client-default`, `network-client-okhttp` and `pubsub-adapter`. + +## 2. Build clients through the door builders + +The client constructors are no longer public. Construct through the builder of the artifact you +depend on — that call is what declares your side. + +**Before (1.x):** + +```java +import io.ably.lib.realtime.AblyRealtime; +import io.ably.lib.rest.AblyRest; + +AblyRealtime realtime = new AblyRealtime("xVLyHw.MHOCLg:..."); + +ClientOptions options = new ClientOptions(apiKey); +options.clientId = "bob"; +AblyRealtime configured = new AblyRealtime(options); + +AblyRest rest = new AblyRest(apiKey); +``` + +**After (2.0), on a server:** + +```java +import io.ably.pubsub.realtime.PubSubRealtimeClient; +import io.ably.pubsub.http.PubSubHttpClient; +import io.ably.pubsub.server.PubSubServer; + +PubSubRealtimeClient realtime = PubSubServer.realtimeClientBuilder() + .key("xVLyHw.MHOCLg:...") + .build(); + +PubSubRealtimeClient configured = PubSubServer.realtimeClientBuilder() + .key(apiKey) + .clientId("bob") + .build(); + +PubSubHttpClient http = PubSubServer.httpClientBuilder() + .key(apiKey) + .build(); +``` + +**After (2.0), on a device:** + +```kotlin +import io.ably.pubsub.device.PubSubDevice + +val client = PubSubDevice.clientBuilder() + .key("xVLyHw.MHOCLg:...") + .clientId("bob") + .build() +``` + +Note that the options object is handed to the client rather than copied, and `build()` replaces its +`agents` map with the stamped one; pass `ClientOptions.copy()` if either matters. Your own `agents` +entries are preserved — only the side entry is applied last and cannot be overridden. + +`RealtimeClientFactory` and `HttpClientFactory` exist in the clients' own packages as the seam the +doors construct through. They are not application API; use the builders. + +## 3. Update packages and class names + +Every package moved from `io.ably.lib.*` to `io.ably.pubsub.*`, and the REST-named types moved with +it into `io.ably.pubsub.http`: + +| 1.x | 2.0 | +|-----|-----| +| `io.ably.lib.realtime.AblyRealtime` | `io.ably.pubsub.realtime.PubSubRealtimeClient` | +| `io.ably.lib.rest.AblyRest` | `io.ably.pubsub.http.PubSubHttpClient` | +| `io.ably.lib.rest.Auth` | `io.ably.pubsub.http.Auth` | +| `io.ably.lib.rest.DeviceDetails` | `io.ably.pubsub.http.DeviceDetails` | +| `io.ably.lib.rest.RestAnnotations` | `io.ably.pubsub.http.HttpAnnotations` | +| `io.ably.lib.http.*` (the rest) | `io.ably.pubsub.http.*` | +| `io.ably.lib.types.*`, `io.ably.lib.realtime.*`, `io.ably.lib.push.*`, … | `io.ably.pubsub.types.*`, `io.ably.pubsub.realtime.*`, `io.ably.pubsub.push.*`, … | + +For most codebases the import rewrite is mechanical. Rewrite the REST package first, since it is +the one that does not simply map by prefix: + +```bash +# GNU sed; on macOS use `sed -i ''` +find src -name '*.java' -o -name '*.kt' | xargs sed -i \ + -e 's/io\.ably\.lib\.rest/io.ably.pubsub.http/g' \ + -e 's/io\.ably\.lib/io.ably.pubsub/g' \ + -e 's/AblyRealtime/PubSubRealtimeClient/g' \ + -e 's/AblyRest/PubSubHttpClient/g' +``` + +## 4. Deprecated API removed + +2.0 drops every member 1.x had marked deprecated. + +| Removed | Use instead | +|---------|-------------| +| `new AblyRealtime(…)`, `new AblyRest(…)` | `PubSubDevice.clientBuilder()` / `PubSubServer.realtimeClientBuilder()` / `PubSubServer.httpClientBuilder()` | +| `ChannelOptions.fromCipherKey(byte[])`, `fromCipherKey(String)` | `ChannelOptions.withCipherKey(…)` | +| `Connection.recoveryKey` | `Connection.createRecoveryKey()` | +| `Connection.emit/on/once(ConnectionState, …)` | The `ConnectionEvent`-keyed `EventEmitter` methods, e.g. `connection.on(ConnectionEvent.connected, listener)` | +| `Channel.publish(…, CompletionListener)`, `publishAsync(…, CompletionListener)` | The `Callback` overloads, e.g. `publish(name, data, callback)` | +| `Channel.sync()` | Nothing. It was a no-op logging stub, intended only for internal testing per RTP19. | +| `Auth.authorise(…)` | `Auth.authorize(…)` | +| `Auth.renew()` | `Auth.renewAuth(…)`, which reports completion instead of returning early | +| `TokenDetails.fromJSON(…)`, `TokenRequest.fromJSON(…)` | `fromJsonElement(…)` | +| `ClientOptions.fallbackHostsUseDefault` | Drop it. Default fallback hosts apply automatically; set `fallbackHosts` only for custom hosts. | +| `RegistrationToken.Type.GCM` (Android) | `RegistrationToken.Type.FCM` | + +## 5. Choose the host with `endpoint` + +2.0 replaces `ClientOptions.environment`, `restHost` and `realtimeHost` with a single +`ClientOptions.endpoint` option, and the builder methods `environment(…)`, `restHost(…)` and +`realtimeHost(…)` with `endpoint(…)`. REST requests and the realtime connection now always use the +same host. + +| 1.x | 2.0 | +|-----|-----| +| No host options | No change; traffic moves to `main.realtime.ably.net` (see below) | +| `environment = "sandbox"` | `endpoint = "nonprod:sandbox"` | +| `environment = "acme"` (dedicated cluster) | `endpoint = "acme"` | +| `restHost` / `realtimeHost = "localhost"` | `endpoint = "localhost"` | +| `restHost` and `realtimeHost` set to the same custom host | `endpoint = ""` | +| `restHost` and `realtimeHost` set to different hosts | Not supported; use one host that serves both, or contact Ably | +| Custom `fallbackHosts` | Unchanged | + +How `endpoint` resolves: + +| `endpoint` | Primary host | Default fallback hosts | +|------------|--------------|------------------------| +| Unset | `main.realtime.ably.net` | `main.[a-e].fallback.ably-realtime.com` | +| A routing policy name, e.g. `acme` | `acme.realtime.ably.net` | `acme.[a-e].fallback.ably-realtime.com` | +| `nonprod:` plus a name, e.g. `nonprod:sandbox` | `sandbox.realtime.ably-nonprod.net` | `sandbox.[a-e].fallback.ably-realtime-nonprod.com` | +| A hostname (contains `.` or `::`, or is `localhost`) | The value as given | None | + +An explicit `fallbackHosts` always replaces the default fallback hosts. A custom `port` or `tlsPort` +no longer disables the default fallback hosts. + +**Before (1.x):** + +```java +ClientOptions options = new ClientOptions("xVLyHw.MHOCLg:..."); +options.environment = "sandbox"; +AblyRealtime realtime = new AblyRealtime(options); +``` + +**After (2.0):** + +```java +PubSubRealtimeClient realtime = PubSubServer.realtimeClientBuilder() + .key("xVLyHw.MHOCLg:...") + .endpoint("nonprod:sandbox") + .build(); +``` + +**Firewalls and proxies.** 1.x connected to `rest.ably.io`, `realtime.ably.io` and +`[a-e].ably-realtime.com` by default. If your network restricts outbound traffic, allow +`*.realtime.ably.net` and `*.fallback.ably-realtime.com` before upgrading. diff --git a/android/gradle.properties b/android/gradle.properties deleted file mode 100644 index c08c36bea..000000000 --- a/android/gradle.properties +++ /dev/null @@ -1,4 +0,0 @@ -POM_ARTIFACT_ID=ably-android -POM_NAME=Ably Android client library SDK -POM_DESCRIPTION=An Android Realtime and REST client library SDK for the Ably platform. -POM_PACKAGING=aar diff --git a/android/src/main/java/io/ably/lib/realtime/Channel.java b/android/src/main/java/io/ably/lib/realtime/Channel.java deleted file mode 100644 index c0677ba69..000000000 --- a/android/src/main/java/io/ably/lib/realtime/Channel.java +++ /dev/null @@ -1,26 +0,0 @@ -package io.ably.lib.realtime; - -import io.ably.lib.types.AblyException; -import io.ably.lib.types.ChannelOptions; -import io.ably.lib.push.PushChannel; -import io.ably.lib.liveobjects.LiveObjectsPlugin; - - -public class Channel extends ChannelBase { - /** - * A {@link PushChannel} object. - *

- * Spec: RSH4 - */ - public final PushChannel push; - - Channel(AblyRealtime ably, String name, ChannelOptions options, LiveObjectsPlugin liveObjectsPlugin) throws AblyException { - super(ably, name, options, liveObjectsPlugin); - this.push = ((io.ably.lib.rest.AblyRest) ably).channels.get(name, options).push; - } - - /** - * An interface whereby a client maybe notified of messages changes on a channel. - */ - public interface MessageListener extends ChannelBase.MessageListener {} -} diff --git a/android/src/main/java/io/ably/lib/rest/Channel.java b/android/src/main/java/io/ably/lib/rest/Channel.java deleted file mode 100644 index 9a56b8f2c..000000000 --- a/android/src/main/java/io/ably/lib/rest/Channel.java +++ /dev/null @@ -1,19 +0,0 @@ -package io.ably.lib.rest; - -import io.ably.lib.push.PushChannel; -import io.ably.lib.types.AblyException; -import io.ably.lib.types.ChannelOptions; - -public class Channel extends ChannelBase { - /** - * A {@link PushChannel} object. - *

- * Spec: RSH4 - */ - public final PushChannel push; - - Channel(AblyBase ably, String name, ChannelOptions options) throws AblyException { - super(ably, name, options); - this.push = new PushChannel(this, (AblyRest)ably); - } -} diff --git a/build.gradle.kts b/build.gradle.kts index a98b165b6..398076611 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -10,6 +10,7 @@ plugins { alias(libs.plugins.test.retry) apply false alias(libs.plugins.android.application) apply false alias(libs.plugins.kotlin.android) apply false + alias(libs.plugins.kotlin.multiplatform) apply false alias(libs.plugins.kotlin.compose) apply false } @@ -30,6 +31,56 @@ subprojects { } } +/* + * Release pre-flight: the split ships core, core-android, device and server in lockstep + * (one version, one run), so the set of published artifacts and their + * coordinates are asserted here and the release workflow fails before anything is + * uploaded if they drift. If you add or remove a published module, update this list + * deliberately. + */ +val expectedReleaseArtifacts = sortedSetOf( + "io.ably.pubsub:core:jar", + "io.ably.pubsub:core-android:aar", + "io.ably.pubsub:device:jar", + "io.ably.pubsub:server:jar", + "io.ably.pubsub:liveobjects:jar", + "io.ably.pubsub:pubsub-adapter:jar", + "io.ably.pubsub:network-client-core:jar", + "io.ably.pubsub:network-client-default:jar", + "io.ably.pubsub:network-client-okhttp:jar", +) + +tasks.register("verifyReleaseArtifacts") { + description = "Asserts the published artifact set, group and lockstep version before a release." + doLast { + val rootVersion = project.property("VERSION_NAME") as String + val actual = sortedSetOf() + subprojects.filter { it.pluginManager.hasPlugin("com.vanniktech.maven.publish") }.forEach { p -> + val artifactId = p.findProperty("POM_ARTIFACT_ID") + ?: error("${p.path} applies maven-publish but has no POM_ARTIFACT_ID") + val packaging = p.findProperty("POM_PACKAGING") ?: "jar" + // The version each module publishes at comes from its effective VERSION_NAME + // (a module-local gradle.properties can override the root's — exactly the + // lockstep drift this guards against). + val moduleVersion = p.findProperty("VERSION_NAME") + if (moduleVersion != rootVersion) { + error("Lockstep violation: ${p.path} has VERSION_NAME $moduleVersion, expected $rootVersion") + } + val group = p.findProperty("GROUP") + actual.add("$group:$artifactId:$packaging") + } + if (actual != expectedReleaseArtifacts) { + error( + "Published artifact set does not match the expected release set.\n" + + " expected: $expectedReleaseArtifacts\n" + + " actual: $actual\n" + + "If this change is deliberate, update expectedReleaseArtifacts in build.gradle.kts." + ) + } + logger.lifecycle("Release pre-flight OK: ${actual.size} artifacts at $rootVersion: $actual") + } +} + configure(subprojects) { pluginManager.withPlugin("com.vanniktech.maven.publish") { extensions.configure { diff --git a/android/.gitignore b/core-android/.gitignore similarity index 100% rename from android/.gitignore rename to core-android/.gitignore diff --git a/android/build.gradle.kts b/core-android/build.gradle.kts similarity index 93% rename from android/build.gradle.kts rename to core-android/build.gradle.kts index 50a11c309..e714135c5 100644 --- a/android/build.gradle.kts +++ b/core-android/build.gradle.kts @@ -4,14 +4,14 @@ plugins { } android { - namespace = "io.ably.lib" + namespace = "io.ably.pubsub" defaultConfig { minSdk = 19 compileSdk = 34 buildConfigField("String", "LIBRARY_NAME", "\"android\"") buildConfigField("String", "VERSION", "\"${property("VERSION_NAME")}\"") testInstrumentationRunner = "android.support.test.runner.AndroidJUnitRunner" - testInstrumentationRunnerArguments["class"] = "io.ably.lib.test.android.AndroidPushTest" + testInstrumentationRunnerArguments["class"] = "io.ably.pubsub.test.android.AndroidPushTest" testInstrumentationRunnerArguments["timeout_msec"] = "300000" consumerProguardFiles("proguard.txt") } diff --git a/core-android/gradle.properties b/core-android/gradle.properties new file mode 100644 index 000000000..09e1922d6 --- /dev/null +++ b/core-android/gradle.properties @@ -0,0 +1,4 @@ +POM_ARTIFACT_ID=core-android +POM_NAME=Ably Pub/Sub core (Android) +POM_DESCRIPTION=Internal implementation artifact for Ably's own Pub/Sub device/server packages. Not intended for direct use: depend on io.ably.pubsub:device instead. +POM_PACKAGING=aar diff --git a/android/proguard.txt b/core-android/proguard.txt similarity index 53% rename from android/proguard.txt rename to core-android/proguard.txt index de4affb05..597b1306e 100644 --- a/android/proguard.txt +++ b/core-android/proguard.txt @@ -1,31 +1,31 @@ --keep public class io.ably.lib.transport.WebSocketTransport$Factory {*;} --keep class io.ably.lib.types.** {*;} +-keep public class io.ably.pubsub.transport.WebSocketTransport$Factory {*;} +-keep class io.ably.pubsub.types.** {*;} # LiveObjects implementations are resolved at runtime via Class.forName(...) + # getDeclaredConstructor(...).newInstance(...) against hard-coded class-name strings # (see LiveObjectsPlugin.Factory, ObjectSerializer.Holder, LiveCounter#create and # LiveMap#create). R8 must not rename or strip these classes or their reflectively # invoked constructors. --keep class io.ably.lib.liveobjects.DefaultLiveObjectsPlugin { (...); } --keep class io.ably.lib.liveobjects.serialization.DefaultObjectsSerializer { (...); } --keep class io.ably.lib.liveobjects.value.livecounter.DefaultLiveCounter { (...); } --keep class io.ably.lib.liveobjects.value.livemap.DefaultLiveMap { (...); } +-keep class io.ably.pubsub.liveobjects.DefaultLiveObjectsPlugin { (...); } +-keep class io.ably.pubsub.liveobjects.serialization.DefaultObjectsSerializer { (...); } +-keep class io.ably.pubsub.liveobjects.value.livecounter.DefaultLiveCounter { (...); } +-keep class io.ably.pubsub.liveobjects.value.livemap.DefaultLiveMap { (...); } # ObjectJsonSerializer and WireObjectDataJsonSerializer are instantiated reflectively # by Gson via @JsonAdapter annotations (on ProtocolMessage and WireObjectData # respectively); keep their no-arg constructors. --keep class io.ably.lib.liveobjects.serialization.ObjectJsonSerializer { (...); } --keep class io.ably.lib.liveobjects.serialization.WireObjectDataJsonSerializer { (...); } +-keep class io.ably.pubsub.liveobjects.serialization.ObjectJsonSerializer { (...); } +-keep class io.ably.pubsub.liveobjects.serialization.WireObjectDataJsonSerializer { (...); } # The Wire* object model is (de)serialized to/from JSON by Gson via field-name # reflection (DefaultObjectsSerializer -> JsonSerialization.gson.fromJson/toJsonTree). # R8 must not rename or strip these fields or JSON transport silently breaks. Mirrors -# the io.ably.lib.types.** rule above. (The MessagePack path uses explicit string keys +# the io.ably.pubsub.types.** rule above. (The MessagePack path uses explicit string keys # and is unaffected.) --keep class io.ably.lib.liveobjects.message.** { *; } +-keep class io.ably.pubsub.liveobjects.message.** { *; } -keep class org.msgpack.core.** {*;} --keepclasseswithmembers class io.ably.lib.rest.Auth** {*;} +-keepclasseswithmembers class io.ably.pubsub.http.Auth** {*;} -keep class com.google.gson.** {*;} -dontwarn org.msgpack.core.buffer.** -dontwarn org.slf4j.** diff --git a/android/src/androidTest/java/io/ably/lib/push/LocalDeviceStorageTest.java b/core-android/src/androidTest/java/io/ably/pubsub/push/LocalDeviceStorageTest.java similarity index 98% rename from android/src/androidTest/java/io/ably/lib/push/LocalDeviceStorageTest.java rename to core-android/src/androidTest/java/io/ably/pubsub/push/LocalDeviceStorageTest.java index 8f1982ec4..3d56788cb 100644 --- a/android/src/androidTest/java/io/ably/lib/push/LocalDeviceStorageTest.java +++ b/core-android/src/androidTest/java/io/ably/pubsub/push/LocalDeviceStorageTest.java @@ -1,13 +1,12 @@ -package io.ably.lib.push; +package io.ably.pubsub.push; import android.content.Context; import android.support.test.runner.AndroidJUnit4; -import io.ably.lib.types.RegistrationToken; +import io.ably.pubsub.types.RegistrationToken; import org.junit.BeforeClass; import org.junit.Test; import org.junit.runner.RunWith; -import java.lang.reflect.Field; import java.util.HashMap; import static android.support.test.InstrumentationRegistry.getContext; diff --git a/android/src/androidTest/java/io/ably/lib/test/RetryTestRule.java b/core-android/src/androidTest/java/io/ably/pubsub/test/RetryTestRule.java similarity index 98% rename from android/src/androidTest/java/io/ably/lib/test/RetryTestRule.java rename to core-android/src/androidTest/java/io/ably/pubsub/test/RetryTestRule.java index 6584ae3b0..10bc6baf5 100644 --- a/android/src/androidTest/java/io/ably/lib/test/RetryTestRule.java +++ b/core-android/src/androidTest/java/io/ably/pubsub/test/RetryTestRule.java @@ -1,4 +1,4 @@ -package io.ably.lib.test; +package io.ably.pubsub.test; import org.junit.rules.TestRule; import org.junit.runner.Description; diff --git a/android/src/androidTest/java/io/ably/lib/test/android/AndroidPushTest.java b/core-android/src/androidTest/java/io/ably/pubsub/test/android/AndroidPushTest.java similarity index 95% rename from android/src/androidTest/java/io/ably/lib/test/android/AndroidPushTest.java rename to core-android/src/androidTest/java/io/ably/pubsub/test/android/AndroidPushTest.java index 6efcc83f1..8e650717b 100644 --- a/android/src/androidTest/java/io/ably/lib/test/android/AndroidPushTest.java +++ b/core-android/src/androidTest/java/io/ably/pubsub/test/android/AndroidPushTest.java @@ -1,4 +1,4 @@ -package io.ably.lib.test.android; +package io.ably.pubsub.test.android; import android.content.BroadcastReceiver; import android.content.Context; @@ -11,53 +11,55 @@ import android.util.Log; import androidx.localbroadcastmanager.content.LocalBroadcastManager; import com.google.gson.JsonObject; -import io.ably.lib.debug.DebugOptions; -import io.ably.lib.http.HttpCore; -import io.ably.lib.push.ActivationContext; -import io.ably.lib.push.ActivationStateMachine; -import io.ably.lib.push.ActivationStateMachine.AfterRegistrationSyncFailed; -import io.ably.lib.push.ActivationStateMachine.CalledActivate; -import io.ably.lib.push.ActivationStateMachine.CalledDeactivate; -import io.ably.lib.push.ActivationStateMachine.Deregistered; -import io.ably.lib.push.ActivationStateMachine.DeregistrationFailed; -import io.ably.lib.push.ActivationStateMachine.Event; -import io.ably.lib.push.ActivationStateMachine.GettingDeviceRegistrationFailed; -import io.ably.lib.push.ActivationStateMachine.GotDeviceRegistration; -import io.ably.lib.push.ActivationStateMachine.GotPushDeviceDetails; -import io.ably.lib.push.ActivationStateMachine.NotActivated; -import io.ably.lib.push.ActivationStateMachine.RegistrationSynced; -import io.ably.lib.push.ActivationStateMachine.State; -import io.ably.lib.push.ActivationStateMachine.SyncRegistrationFailed; -import io.ably.lib.push.ActivationStateMachine.WaitingForDeregistration; -import io.ably.lib.push.ActivationStateMachine.WaitingForDeviceRegistration; -import io.ably.lib.push.ActivationStateMachine.WaitingForNewPushDeviceDetails; -import io.ably.lib.push.ActivationStateMachine.WaitingForPushDeviceDetails; -import io.ably.lib.push.ActivationStateMachine.WaitingForRegistrationSync; -import io.ably.lib.push.LocalDevice; -import io.ably.lib.push.Push; -import io.ably.lib.push.PushBase; -import io.ably.lib.push.PushChannel; -import io.ably.lib.realtime.AblyRealtime; -import io.ably.lib.rest.AblyRest; -import io.ably.lib.rest.Auth; -import io.ably.lib.rest.Channel; -import io.ably.lib.rest.DeviceDetails; -import io.ably.lib.test.RetryTestRule; -import io.ably.lib.test.common.Helpers; -import io.ably.lib.test.common.Helpers.AsyncWaiter; -import io.ably.lib.test.common.Helpers.CompletionWaiter; -import io.ably.lib.test.common.Setup; -import io.ably.lib.test.util.TestCases; -import io.ably.lib.types.AblyException; -import io.ably.lib.types.Callback; -import io.ably.lib.types.ClientOptions; -import io.ably.lib.types.ErrorInfo; -import io.ably.lib.types.Param; -import io.ably.lib.types.RegistrationToken; -import io.ably.lib.util.Base64Coder; -import io.ably.lib.util.IntentUtils; -import io.ably.lib.util.JsonUtils; -import io.ably.lib.util.Serialisation; +import io.ably.pubsub.debug.DebugOptions; +import io.ably.pubsub.http.HttpCore; +import io.ably.pubsub.push.ActivationContext; +import io.ably.pubsub.push.ActivationStateMachine; +import io.ably.pubsub.push.ActivationStateMachine.AfterRegistrationSyncFailed; +import io.ably.pubsub.push.ActivationStateMachine.CalledActivate; +import io.ably.pubsub.push.ActivationStateMachine.CalledDeactivate; +import io.ably.pubsub.push.ActivationStateMachine.Deregistered; +import io.ably.pubsub.push.ActivationStateMachine.DeregistrationFailed; +import io.ably.pubsub.push.ActivationStateMachine.Event; +import io.ably.pubsub.push.ActivationStateMachine.GettingDeviceRegistrationFailed; +import io.ably.pubsub.push.ActivationStateMachine.GotDeviceRegistration; +import io.ably.pubsub.push.ActivationStateMachine.GotPushDeviceDetails; +import io.ably.pubsub.push.ActivationStateMachine.NotActivated; +import io.ably.pubsub.push.ActivationStateMachine.RegistrationSynced; +import io.ably.pubsub.push.ActivationStateMachine.State; +import io.ably.pubsub.push.ActivationStateMachine.SyncRegistrationFailed; +import io.ably.pubsub.push.ActivationStateMachine.WaitingForDeregistration; +import io.ably.pubsub.push.ActivationStateMachine.WaitingForDeviceRegistration; +import io.ably.pubsub.push.ActivationStateMachine.WaitingForNewPushDeviceDetails; +import io.ably.pubsub.push.ActivationStateMachine.WaitingForPushDeviceDetails; +import io.ably.pubsub.push.ActivationStateMachine.WaitingForRegistrationSync; +import io.ably.pubsub.push.LocalDevice; +import io.ably.pubsub.push.Push; +import io.ably.pubsub.push.PushBase; +import io.ably.pubsub.push.PushChannel; +import io.ably.pubsub.realtime.PubSubRealtimeClient; +import io.ably.pubsub.realtime.RealtimeClientFactory; +import io.ably.pubsub.http.HttpClientFactory; +import io.ably.pubsub.http.PubSubHttpClient; +import io.ably.pubsub.http.Auth; +import io.ably.pubsub.http.Channel; +import io.ably.pubsub.http.DeviceDetails; +import io.ably.pubsub.test.RetryTestRule; +import io.ably.pubsub.test.common.Helpers; +import io.ably.pubsub.test.common.Helpers.AsyncWaiter; +import io.ably.pubsub.test.common.Helpers.CompletionWaiter; +import io.ably.pubsub.test.common.Setup; +import io.ably.pubsub.test.util.TestCases; +import io.ably.pubsub.types.AblyException; +import io.ably.pubsub.types.Callback; +import io.ably.pubsub.types.ClientOptions; +import io.ably.pubsub.types.ErrorInfo; +import io.ably.pubsub.types.Param; +import io.ably.pubsub.types.RegistrationToken; +import io.ably.pubsub.util.Base64Coder; +import io.ably.pubsub.util.IntentUtils; +import io.ably.pubsub.util.JsonUtils; +import io.ably.pubsub.util.Serialisation; import java9.util.stream.StreamSupport; import org.junit.AfterClass; @@ -73,10 +75,10 @@ import java.util.concurrent.TimeUnit; import static android.support.test.InstrumentationRegistry.getContext; -import static io.ably.lib.test.common.Helpers.assertArrayUnorderedEquals; -import static io.ably.lib.test.common.Helpers.assertInstanceOf; -import static io.ably.lib.test.common.Helpers.assertSize; -import static io.ably.lib.util.Serialisation.gson; +import static io.ably.pubsub.test.common.Helpers.assertArrayUnorderedEquals; +import static io.ably.pubsub.test.common.Helpers.assertInstanceOf; +import static io.ably.pubsub.test.common.Helpers.assertSize; +import static io.ably.pubsub.util.Serialisation.gson; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; @@ -93,10 +95,10 @@ public class AndroidPushTest { private class TestActivation { private Helpers.RawHttpTracker httpTracker; - private AblyRest rest; + private PubSubHttpClient rest; private TestActivationContext activationContext; private TestActivationStateMachine machine; - private AblyRest adminRest; + private PubSubHttpClient adminHttp; TestActivation() { this(null); @@ -136,13 +138,13 @@ public class Options { } activationContext.setActivationStateMachine(machine); - rest = new AblyRest(options); + rest = HttpClientFactory.create(options); rest.auth.authorize(null, null); activationContext.setAbly(rest); rest.setAndroidContext(context); - adminRest = new AblyRest(options); - adminRest.auth.authorize(new Auth.TokenParams() {{ + adminHttp = HttpClientFactory.create(options); + adminHttp.auth.authorize(new Auth.TokenParams() {{ clientId = Auth.WILDCARD_CLIENTID; }}, null); } catch(final AblyException e) { @@ -466,7 +468,7 @@ public void push_clientId_from_server() throws InterruptedException, AblyExcepti activation.rest.push.activate(false); activated.waitFor(); } finally { - activation.adminRest.push.admin.deviceRegistrations.remove(activation.rest.device().id); + activation.adminHttp.push.admin.deviceRegistrations.remove(activation.rest.device().id); } assertEquals("testClient", activation.rest.device().clientId); @@ -1399,10 +1401,10 @@ public void run() throws Exception { }; try { - testActivation.adminRest.push.admin.deviceRegistrations.save(otherDevice); + testActivation.adminHttp.push.admin.deviceRegistrations.save(otherDevice); for (PushBase.ChannelSubscription sub : fixtures) { - testActivation.adminRest.push.admin.channelSubscriptions.save(sub); + testActivation.adminHttp.push.admin.channelSubscriptions.save(sub); } Param[] params = Param.array(new Param("deviceId", deviceId)); @@ -1423,9 +1425,9 @@ public void run() throws Exception { assertArrayUnorderedEquals(expected.toArray(), got); } finally { - testActivation.adminRest.push.admin.deviceRegistrations.remove(otherDevice); + testActivation.adminHttp.push.admin.deviceRegistrations.remove(otherDevice); for (PushBase.ChannelSubscription sub : fixtures) { - testActivation.adminRest.push.admin.channelSubscriptions.remove(sub); + testActivation.adminHttp.push.admin.channelSubscriptions.remove(sub); } } } @@ -1442,7 +1444,7 @@ public void run() throws Exception { @Test @SdkSuppress(minSdkVersion = 21) public void Realtime_push_interface() throws Exception { - AblyRealtime realtime = new AblyRealtime(new ClientOptions() {{ + PubSubRealtimeClient realtime = RealtimeClientFactory.create(new ClientOptions() {{ autoConnect = false; key = "madeup"; }}); diff --git a/android/src/androidTest/java/io/ably/lib/test/android/AndroidSuite.java b/core-android/src/androidTest/java/io/ably/pubsub/test/android/AndroidSuite.java similarity index 85% rename from android/src/androidTest/java/io/ably/lib/test/android/AndroidSuite.java rename to core-android/src/androidTest/java/io/ably/pubsub/test/android/AndroidSuite.java index 9c96459b8..4d5eabc19 100644 --- a/android/src/androidTest/java/io/ably/lib/test/android/AndroidSuite.java +++ b/core-android/src/androidTest/java/io/ably/pubsub/test/android/AndroidSuite.java @@ -1,4 +1,4 @@ -package io.ably.lib.test.android; +package io.ably.pubsub.test.android; import org.junit.AfterClass; import org.junit.BeforeClass; @@ -15,11 +15,12 @@ import fi.iki.elonen.NanoHTTPD; import fi.iki.elonen.router.RouterNanoHTTPD; -import io.ably.lib.rest.AblyRest; -import io.ably.lib.test.common.Setup; -import io.ably.lib.transport.Defaults; -import io.ably.lib.types.AblyException; -import io.ably.lib.types.ClientOptions; +import io.ably.pubsub.http.HttpClientFactory; +import io.ably.pubsub.http.PubSubHttpClient; +import io.ably.pubsub.test.common.Setup; +import io.ably.pubsub.transport.Defaults; +import io.ably.pubsub.types.AblyException; +import io.ably.pubsub.types.ClientOptions; /** * Tests specific for Android @@ -55,8 +56,8 @@ public void android_http_header_test() { ClientOptions opts = new ClientOptions(testVars.keys[0].keyStr); opts.tls = false; opts.port = server.getListeningPort(); - opts.restHost = "localhost"; - AblyRest ably = new AblyRest(opts); + opts.endpoint = "localhost"; + PubSubHttpClient ably = HttpClientFactory.create(opts); ably.time(); diff --git a/android/src/androidTest/java/io/ably/lib/test/android/EventTest.java b/core-android/src/androidTest/java/io/ably/pubsub/test/android/EventTest.java similarity index 74% rename from android/src/androidTest/java/io/ably/lib/test/android/EventTest.java rename to core-android/src/androidTest/java/io/ably/pubsub/test/android/EventTest.java index 8eb5c6304..65bb1df29 100644 --- a/android/src/androidTest/java/io/ably/lib/test/android/EventTest.java +++ b/core-android/src/androidTest/java/io/ably/pubsub/test/android/EventTest.java @@ -1,16 +1,16 @@ -package io.ably.lib.test.android; - -import io.ably.lib.push.ActivationStateMachine.CalledActivate; -import io.ably.lib.push.ActivationStateMachine.CalledDeactivate; -import io.ably.lib.push.ActivationStateMachine.Deregistered; -import io.ably.lib.push.ActivationStateMachine.Event; -import io.ably.lib.push.ActivationStateMachine.GotDeviceRegistration; -import io.ably.lib.push.ActivationStateMachine.GotPushDeviceDetails; -import io.ably.lib.push.ActivationStateMachine.RegistrationSynced; -import io.ably.lib.push.ActivationStateMachine.GettingDeviceRegistrationFailed; -import io.ably.lib.push.ActivationStateMachine.GettingPushDeviceDetailsFailed; -import io.ably.lib.push.ActivationStateMachine.SyncRegistrationFailed; -import io.ably.lib.push.ActivationStateMachine.DeregistrationFailed; +package io.ably.pubsub.test.android; + +import io.ably.pubsub.push.ActivationStateMachine.CalledActivate; +import io.ably.pubsub.push.ActivationStateMachine.CalledDeactivate; +import io.ably.pubsub.push.ActivationStateMachine.Deregistered; +import io.ably.pubsub.push.ActivationStateMachine.Event; +import io.ably.pubsub.push.ActivationStateMachine.GotDeviceRegistration; +import io.ably.pubsub.push.ActivationStateMachine.GotPushDeviceDetails; +import io.ably.pubsub.push.ActivationStateMachine.RegistrationSynced; +import io.ably.pubsub.push.ActivationStateMachine.GettingDeviceRegistrationFailed; +import io.ably.pubsub.push.ActivationStateMachine.GettingPushDeviceDetailsFailed; +import io.ably.pubsub.push.ActivationStateMachine.SyncRegistrationFailed; +import io.ably.pubsub.push.ActivationStateMachine.DeregistrationFailed; import org.junit.Test; import static org.junit.Assert.assertEquals; diff --git a/android/src/androidTest/java/io/ably/lib/test/loader/ArgumentLoader.java b/core-android/src/androidTest/java/io/ably/pubsub/test/loader/ArgumentLoader.java similarity index 88% rename from android/src/androidTest/java/io/ably/lib/test/loader/ArgumentLoader.java rename to core-android/src/androidTest/java/io/ably/pubsub/test/loader/ArgumentLoader.java index 03bfbaae9..99cf07c6f 100644 --- a/android/src/androidTest/java/io/ably/lib/test/loader/ArgumentLoader.java +++ b/core-android/src/androidTest/java/io/ably/pubsub/test/loader/ArgumentLoader.java @@ -1,4 +1,4 @@ -package io.ably.lib.test.loader; +package io.ably.pubsub.test.loader; import android.os.Bundle; import android.support.test.InstrumentationRegistry; diff --git a/android/src/androidTest/java/io/ably/lib/test/loader/ResourceLoader.java b/core-android/src/androidTest/java/io/ably/pubsub/test/loader/ResourceLoader.java similarity index 96% rename from android/src/androidTest/java/io/ably/lib/test/loader/ResourceLoader.java rename to core-android/src/androidTest/java/io/ably/pubsub/test/loader/ResourceLoader.java index 29c754c82..f04fc473e 100644 --- a/android/src/androidTest/java/io/ably/lib/test/loader/ResourceLoader.java +++ b/core-android/src/androidTest/java/io/ably/pubsub/test/loader/ResourceLoader.java @@ -1,4 +1,4 @@ -package io.ably.lib.test.loader; +package io.ably.pubsub.test.loader; import android.content.Context; import android.support.test.InstrumentationRegistry; diff --git a/android/src/androidTest/java/io/ably/lib/types/RegistrationTokenTypeTest.java b/core-android/src/androidTest/java/io/ably/pubsub/types/RegistrationTokenTypeTest.java similarity index 72% rename from android/src/androidTest/java/io/ably/lib/types/RegistrationTokenTypeTest.java rename to core-android/src/androidTest/java/io/ably/pubsub/types/RegistrationTokenTypeTest.java index 527e3da2f..a93162ca6 100644 --- a/android/src/androidTest/java/io/ably/lib/types/RegistrationTokenTypeTest.java +++ b/core-android/src/androidTest/java/io/ably/pubsub/types/RegistrationTokenTypeTest.java @@ -1,4 +1,4 @@ -package io.ably.lib.types; +package io.ably.pubsub.types; import org.junit.Test; @@ -17,15 +17,6 @@ public void fromNameParseCorrectly() { assertEquals(RegistrationToken.Type.FCM, RegistrationToken.Type.fromName("Fcm")); assertEquals(RegistrationToken.Type.FCM, RegistrationToken.Type.fromName("FCm")); assertEquals(RegistrationToken.Type.FCM, RegistrationToken.Type.fromName("fCm")); - - assertEquals(RegistrationToken.Type.GCM, RegistrationToken.Type.fromName("GCM")); - assertEquals(RegistrationToken.Type.GCM, RegistrationToken.Type.fromName("gCM")); - assertEquals(RegistrationToken.Type.GCM, RegistrationToken.Type.fromName("gcM")); - assertEquals(RegistrationToken.Type.GCM, RegistrationToken.Type.fromName("gcm")); - assertEquals(RegistrationToken.Type.GCM, RegistrationToken.Type.fromName("GcM")); - assertEquals(RegistrationToken.Type.GCM, RegistrationToken.Type.fromName("Gcm")); - assertEquals(RegistrationToken.Type.GCM, RegistrationToken.Type.fromName("GCm")); - assertEquals(RegistrationToken.Type.GCM, RegistrationToken.Type.fromName("gCm")); } @Test @@ -39,6 +30,8 @@ public void fromNameParseFailure() { assertNull(RegistrationToken.Type.fromName("FĆM\'")); assertNull(RegistrationToken.Type.fromName("FĆM\"")); assertNull(RegistrationToken.Type.fromName("\nFCM")); + assertNull(RegistrationToken.Type.fromName("GCM")); + assertNull(RegistrationToken.Type.fromName("gcm")); assertNull(RegistrationToken.Type.fromName("GÇM")); assertNull(RegistrationToken.Type.fromName("\\GCM")); assertNull(RegistrationToken.Type.fromName("\'GCM")); @@ -53,7 +46,6 @@ public void fromNameParseFailure() { @Test public void toNameProducesNameCorrectly() { assertEquals("fcm", new RegistrationToken(RegistrationToken.Type.FCM, "token").type.toName()); - assertEquals("gcm", new RegistrationToken(RegistrationToken.Type.GCM, "token").type.toName()); } } diff --git a/android/src/main/.gitignore b/core-android/src/main/.gitignore similarity index 100% rename from android/src/main/.gitignore rename to core-android/src/main/.gitignore diff --git a/android/src/main/AndroidManifest.xml b/core-android/src/main/AndroidManifest.xml similarity index 100% rename from android/src/main/AndroidManifest.xml rename to core-android/src/main/AndroidManifest.xml diff --git a/core-android/src/main/java/io/ably/pubsub/http/Channel.java b/core-android/src/main/java/io/ably/pubsub/http/Channel.java new file mode 100644 index 000000000..0b3743460 --- /dev/null +++ b/core-android/src/main/java/io/ably/pubsub/http/Channel.java @@ -0,0 +1,19 @@ +package io.ably.pubsub.http; + +import io.ably.pubsub.push.PushChannel; +import io.ably.pubsub.types.AblyException; +import io.ably.pubsub.types.ChannelOptions; + +public class Channel extends ChannelBase { + /** + * A {@link PushChannel} object. + *

+ * Spec: RSH4 + */ + public final PushChannel push; + + Channel(PubSubBase ably, String name, ChannelOptions options) throws AblyException { + super(ably, name, options); + this.push = new PushChannel(this, (PubSubHttpClient)ably); + } +} diff --git a/android/src/main/java/io/ably/lib/rest/AblyRest.java b/core-android/src/main/java/io/ably/pubsub/http/PubSubHttpClient.java similarity index 71% rename from android/src/main/java/io/ably/lib/rest/AblyRest.java rename to core-android/src/main/java/io/ably/pubsub/http/PubSubHttpClient.java index 7f04feb2a..160159025 100644 --- a/android/src/main/java/io/ably/lib/rest/AblyRest.java +++ b/core-android/src/main/java/io/ably/pubsub/http/PubSubHttpClient.java @@ -1,11 +1,11 @@ -package io.ably.lib.rest; +package io.ably.pubsub.http; import android.content.Context; -import io.ably.lib.push.LocalDevice; -import io.ably.lib.types.AblyException; -import io.ably.lib.types.ClientOptions; -import io.ably.lib.util.AndroidPlatformAgentProvider; -import io.ably.lib.util.Log; +import io.ably.pubsub.push.LocalDevice; +import io.ably.pubsub.types.AblyException; +import io.ably.pubsub.types.ClientOptions; +import io.ably.pubsub.util.AndroidPlatformAgentProvider; +import io.ably.pubsub.util.Log; /** * A client that offers a simple stateless API to interact directly with Ably's REST API. @@ -13,26 +13,19 @@ * This class implements {@link AutoCloseable} so you can use it in * try-with-resources constructs and have the JDK close it for you. */ -public class AblyRest extends AblyBase { - /** - * Constructs a client object using an Ably API key or token string. - *

- * Spec: RSC1 - * @param key The Ably API key or token string used to validate the client. - * @throws AblyException - */ - public AblyRest(String key) throws AblyException { - super(key, new AndroidPlatformAgentProvider()); - } - +public class PubSubHttpClient extends PubSubBase { /** * Construct a client object using an Ably {@link ClientOptions} object. *

+ * Not public: a client is obtained from the builders of the {@code io.ably.pubsub:device} or + * {@code io.ably.pubsub:server} artifact, which name the side of the connection your code + * runs on. {@link HttpClientFactory} is the seam those builders construct through. + *

* Spec: RSC1 * @param options A {@link ClientOptions} object to configure the client connection to Ably. * @throws AblyException */ - public AblyRest(ClientOptions options) throws AblyException { + protected PubSubHttpClient(ClientOptions options) throws AblyException { super(options, new AndroidPlatformAgentProvider()); } @@ -71,5 +64,5 @@ protected void onClientIdSet(String clientId) { } } - private static final String TAG = AblyRest.class.getName(); + private static final String TAG = PubSubHttpClient.class.getName(); } diff --git a/android/src/main/java/io/ably/lib/platform/AndroidNetworkConnectivity.java b/core-android/src/main/java/io/ably/pubsub/platform/AndroidNetworkConnectivity.java similarity index 95% rename from android/src/main/java/io/ably/lib/platform/AndroidNetworkConnectivity.java rename to core-android/src/main/java/io/ably/pubsub/platform/AndroidNetworkConnectivity.java index 8510d8475..36632854e 100644 --- a/android/src/main/java/io/ably/lib/platform/AndroidNetworkConnectivity.java +++ b/core-android/src/main/java/io/ably/pubsub/platform/AndroidNetworkConnectivity.java @@ -1,4 +1,4 @@ -package io.ably.lib.platform; +package io.ably.pubsub.platform; import android.content.BroadcastReceiver; import android.content.Context; @@ -6,8 +6,8 @@ import android.content.IntentFilter; import android.net.ConnectivityManager; import android.net.NetworkInfo; -import io.ably.lib.transport.NetworkConnectivity; -import io.ably.lib.types.ErrorInfo; +import io.ably.pubsub.transport.NetworkConnectivity; +import io.ably.pubsub.types.ErrorInfo; import java.util.WeakHashMap; diff --git a/android/src/main/java/io/ably/lib/platform/Platform.java b/core-android/src/main/java/io/ably/pubsub/platform/Platform.java similarity index 85% rename from android/src/main/java/io/ably/lib/platform/Platform.java rename to core-android/src/main/java/io/ably/pubsub/platform/Platform.java index 901b71be5..da68a9ad6 100644 --- a/android/src/main/java/io/ably/lib/platform/Platform.java +++ b/core-android/src/main/java/io/ably/pubsub/platform/Platform.java @@ -1,11 +1,11 @@ -package io.ably.lib.platform; +package io.ably.pubsub.platform; import android.content.Context; -import io.ably.lib.transport.NetworkConnectivity; -import io.ably.lib.transport.NetworkConnectivity.DelegatedNetworkConnectivity; -import io.ably.lib.types.AblyException; -import io.ably.lib.types.ErrorInfo; -import io.ably.lib.util.Log; +import io.ably.pubsub.transport.NetworkConnectivity; +import io.ably.pubsub.transport.NetworkConnectivity.DelegatedNetworkConnectivity; +import io.ably.pubsub.types.AblyException; +import io.ably.pubsub.types.ErrorInfo; +import io.ably.pubsub.util.Log; public class Platform { public static final String name = "android"; diff --git a/android/src/main/java/io/ably/lib/push/ActivationContext.java b/core-android/src/main/java/io/ably/pubsub/push/ActivationContext.java similarity index 88% rename from android/src/main/java/io/ably/lib/push/ActivationContext.java rename to core-android/src/main/java/io/ably/pubsub/push/ActivationContext.java index 0a2224f07..f9a3c15e6 100644 --- a/android/src/main/java/io/ably/lib/push/ActivationContext.java +++ b/core-android/src/main/java/io/ably/pubsub/push/ActivationContext.java @@ -1,4 +1,4 @@ -package io.ably.lib.push; +package io.ably.pubsub.push; import android.content.Context; import android.content.SharedPreferences; @@ -9,13 +9,14 @@ import java.util.WeakHashMap; -import io.ably.lib.rest.AblyRest; -import io.ably.lib.types.AblyException; -import io.ably.lib.types.Callback; -import io.ably.lib.types.ClientOptions; -import io.ably.lib.types.ErrorInfo; -import io.ably.lib.types.RegistrationToken; -import io.ably.lib.util.Log; +import io.ably.pubsub.http.HttpClientFactory; +import io.ably.pubsub.http.PubSubHttpClient; +import io.ably.pubsub.types.AblyException; +import io.ably.pubsub.types.Callback; +import io.ably.pubsub.types.ClientOptions; +import io.ably.pubsub.types.ErrorInfo; +import io.ably.pubsub.types.RegistrationToken; +import io.ably.pubsub.util.Log; public class ActivationContext { public ActivationContext(Context context) { @@ -55,12 +56,12 @@ public synchronized ActivationStateMachine getActivationStateMachine() { return activationStateMachine; } - public void setAbly(AblyRest ably) { + public void setAbly(PubSubHttpClient ably) { this.ably = ably; this.clientId = ably.auth.clientId; } - AblyRest getAbly() throws AblyException { + PubSubHttpClient getAbly() throws AblyException { if(ably != null) { Log.v(TAG, "getAbly(): returning existing Ably instance"); return ably; @@ -76,19 +77,19 @@ AblyRest getAbly() throws AblyException { throw AblyException.fromErrorInfo(new ErrorInfo("Unable to get Ably library instance; no device identity token", 400, 40000)); } Log.v(TAG, "getAbly(): returning Ably instance using deviceIdentityToken"); - // TODO: We need to persist Ably client options such as the environment with `deviceIdentityToken` and use these options during initialization. - return (ably = new AblyRest(deviceIdentityToken)); + // TODO: We need to persist Ably client options such as the endpoint with `deviceIdentityToken` and use these options during initialization. + return (ably = HttpClientFactory.create(new ClientOptions(deviceIdentityToken))); } /** - * @return AblyRest instance with device identity token auth. We use this instance to perform + * @return PubSubHttpClient instance with device identity token auth. We use this instance to perform * deregistration calls in push activation flow. */ - AblyRest getDeviceIdentityTokenBasedAblyClient(String deviceIdentityToken) throws AblyException { + PubSubHttpClient getDeviceIdentityTokenBasedAblyClient(String deviceIdentityToken) throws AblyException { ClientOptions clientOptions = ably.options.copy(); clientOptions.clearAuthOptions(); clientOptions.token = deviceIdentityToken; - return new AblyRest(clientOptions); + return HttpClientFactory.create(clientOptions); } public boolean setClientId(String clientId, boolean propagateGotPushDeviceDetails) { @@ -149,7 +150,7 @@ public static ActivationContext getActivationContext(Context applicationContext) return getActivationContext(applicationContext, null); } - public static ActivationContext getActivationContext(Context applicationContext, AblyRest ably) { + public static ActivationContext getActivationContext(Context applicationContext, PubSubHttpClient ably) { ActivationContext activationContext; synchronized (activationContexts) { activationContext = activationContexts.get(applicationContext); @@ -187,7 +188,7 @@ public static void setActivationContext(Context applicationContext, ActivationCo activationContexts.put(applicationContext, activationContext); } - protected AblyRest ably; + protected PubSubHttpClient ably; protected String clientId; protected ActivationStateMachine activationStateMachine; protected LocalDevice localDevice; diff --git a/android/src/main/java/io/ably/lib/push/ActivationStateMachine.java b/core-android/src/main/java/io/ably/pubsub/push/ActivationStateMachine.java similarity index 97% rename from android/src/main/java/io/ably/lib/push/ActivationStateMachine.java rename to core-android/src/main/java/io/ably/pubsub/push/ActivationStateMachine.java index ea604ee05..a2b93108a 100644 --- a/android/src/main/java/io/ably/lib/push/ActivationStateMachine.java +++ b/core-android/src/main/java/io/ably/pubsub/push/ActivationStateMachine.java @@ -1,4 +1,4 @@ -package io.ably.lib.push; +package io.ably.pubsub.push; import android.content.BroadcastReceiver; import android.content.Context; @@ -9,21 +9,21 @@ import androidx.localbroadcastmanager.content.LocalBroadcastManager; import com.google.gson.JsonObject; import com.google.gson.JsonPrimitive; -import io.ably.lib.http.Http; -import io.ably.lib.http.HttpCore; -import io.ably.lib.http.HttpScheduler; -import io.ably.lib.http.HttpUtils; -import io.ably.lib.rest.AblyRest; -import io.ably.lib.rest.DeviceDetails; -import io.ably.lib.types.AblyException; -import io.ably.lib.types.Callback; -import io.ably.lib.types.ErrorInfo; -import io.ably.lib.types.Param; -import io.ably.lib.types.RegistrationToken; -import io.ably.lib.util.IntentUtils; -import io.ably.lib.util.Log; -import io.ably.lib.util.ParamsUtils; -import io.ably.lib.util.Serialisation; +import io.ably.pubsub.http.HttpRequester; +import io.ably.pubsub.http.HttpCore; +import io.ably.pubsub.http.HttpScheduler; +import io.ably.pubsub.http.HttpUtils; +import io.ably.pubsub.http.PubSubHttpClient; +import io.ably.pubsub.http.DeviceDetails; +import io.ably.pubsub.types.AblyException; +import io.ably.pubsub.types.Callback; +import io.ably.pubsub.types.ErrorInfo; +import io.ably.pubsub.types.Param; +import io.ably.pubsub.types.RegistrationToken; +import io.ably.pubsub.util.IntentUtils; +import io.ably.pubsub.util.Log; +import io.ably.pubsub.util.ParamsUtils; +import io.ably.pubsub.util.Serialisation; import java.lang.reflect.Field; import java.util.ArrayDeque; @@ -297,7 +297,7 @@ public ActivationStateMachine.State transition(final ActivationStateMachine.Even if (useCustomRegistrar) { machine.invokeCustomRegistration(device, true); } else { - final AblyRest ably; + final PubSubHttpClient ably; try { ably = activationContext.getAbly(); } catch(AblyException ae) { @@ -307,7 +307,7 @@ public ActivationStateMachine.State transition(final ActivationStateMachine.Even return new ActivationStateMachine.NotActivated(machine); } final HttpCore.RequestBody body = HttpUtils.requestBodyFromGson(device.toJsonObject(), ably.options.useBinaryProtocol); - ably.http.request(new Http.Execute() { + ably.http.request(new HttpRequester.Execute() { @Override public void execute(HttpScheduler http, Callback callback) throws AblyException { Param[] params = ParamsUtils.enrichParams(null, ably.options); @@ -660,7 +660,7 @@ private void updateRegistration() { if (useCustomRegistrar) { invokeCustomRegistration(device, false); } else { - final AblyRest ably; + final PubSubHttpClient ably; try { ably = activationContext.getAbly(); } catch(AblyException ae) { @@ -670,7 +670,7 @@ private void updateRegistration() { return; } final HttpCore.RequestBody body = HttpUtils.requestBodyFromGson(device.pushRecipientJsonObject(), ably.options.useBinaryProtocol); - ably.http.request(new Http.Execute() { + ably.http.request(new HttpRequester.Execute() { @Override public void execute(HttpScheduler http, Callback callback) throws AblyException { Param[] params = ParamsUtils.enrichParams(null, ably.options); @@ -693,7 +693,7 @@ public void onError(ErrorInfo reason) { private void validateRegistration() { final LocalDevice device = activationContext.getLocalDevice(); - final AblyRest ably; + final PubSubHttpClient ably; try { ably = activationContext.getAbly(); } catch(AblyException ae) { @@ -714,7 +714,7 @@ private void validateRegistration() { if (useCustomRegistrar) { invokeCustomRegistration(device, false); } else { - ably.http.request(new Http.Execute() { + ably.http.request(new HttpRequester.Execute() { @Override public void execute(HttpScheduler http, Callback callback) throws AblyException { Param[] params = ParamsUtils.enrichParams(null, ably.options); @@ -749,7 +749,7 @@ private void deregister() { if (activationContext.getPreferences().getBoolean(ActivationStateMachine.PersistKeys.PUSH_CUSTOM_REGISTRAR, false)) { invokeCustomDeregistration(device); } else { - final AblyRest ably; + final PubSubHttpClient ably; try { // RSH3d2b: use `deviceIdentityToken` to perform request ably = activationContext.getDeviceIdentityTokenBasedAblyClient(device.deviceIdentityToken); @@ -759,7 +759,7 @@ private void deregister() { handleEvent(new ActivationStateMachine.DeregistrationFailed(reason)); return; } - ably.http.request(new Http.Execute() { + ably.http.request(new HttpRequester.Execute() { @Override public void execute(HttpScheduler http, Callback callback) { Param[] params = ParamsUtils.enrichParams(new Param[0], ably.options); diff --git a/android/src/main/java/io/ably/lib/push/LocalDevice.java b/core-android/src/main/java/io/ably/pubsub/push/LocalDevice.java similarity index 96% rename from android/src/main/java/io/ably/lib/push/LocalDevice.java rename to core-android/src/main/java/io/ably/pubsub/push/LocalDevice.java index bed9d4554..5a05bf3d5 100644 --- a/android/src/main/java/io/ably/lib/push/LocalDevice.java +++ b/core-android/src/main/java/io/ably/pubsub/push/LocalDevice.java @@ -1,13 +1,13 @@ -package io.ably.lib.push; +package io.ably.pubsub.push; import android.content.Context; import android.content.res.Configuration; import com.google.gson.JsonObject; -import io.ably.lib.rest.DeviceDetails; -import io.ably.lib.types.Param; -import io.ably.lib.types.RegistrationToken; -import io.ably.lib.util.Base64Coder; -import io.ably.lib.util.Log; +import io.ably.pubsub.http.DeviceDetails; +import io.ably.pubsub.types.Param; +import io.ably.pubsub.types.RegistrationToken; +import io.ably.pubsub.util.Base64Coder; +import io.ably.pubsub.util.Log; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; diff --git a/android/src/main/java/io/ably/lib/push/Push.java b/core-android/src/main/java/io/ably/pubsub/push/Push.java similarity index 93% rename from android/src/main/java/io/ably/lib/push/Push.java rename to core-android/src/main/java/io/ably/pubsub/push/Push.java index 66960ed2b..05be1ee29 100644 --- a/android/src/main/java/io/ably/lib/push/Push.java +++ b/core-android/src/main/java/io/ably/pubsub/push/Push.java @@ -1,15 +1,15 @@ -package io.ably.lib.push; +package io.ably.pubsub.push; import android.content.Context; import android.content.SharedPreferences; import android.preference.PreferenceManager; -import io.ably.lib.http.HttpUtils; -import io.ably.lib.rest.AblyBase; -import io.ably.lib.rest.AblyRest; -import io.ably.lib.types.AblyException; -import io.ably.lib.types.ErrorInfo; -import io.ably.lib.types.Param; -import io.ably.lib.util.Log; +import io.ably.pubsub.http.HttpUtils; +import io.ably.pubsub.http.PubSubBase; +import io.ably.pubsub.http.PubSubHttpClient; +import io.ably.pubsub.types.AblyException; +import io.ably.pubsub.types.ErrorInfo; +import io.ably.pubsub.types.Param; +import io.ably.pubsub.util.Log; import java.util.Arrays; @@ -18,7 +18,7 @@ */ public class Push extends PushBase { - public Push(AblyBase rest) { + public Push(PubSubBase rest) { super(rest); } @@ -104,7 +104,7 @@ public ActivationContext getActivationContext() throws AblyException { if (activationContext == null) { Log.v(TAG, "getActivationContext(): creating a new context and returning that"); Context applicationContext = getApplicationContext(); - activationContext = ActivationContext.getActivationContext(applicationContext, (AblyRest)rest); + activationContext = ActivationContext.getActivationContext(applicationContext, (PubSubHttpClient)rest); } else { Log.v(TAG, "getActivationContext(): returning existing content"); } diff --git a/android/src/main/java/io/ably/lib/push/PushChannel.java b/core-android/src/main/java/io/ably/pubsub/push/PushChannel.java similarity index 86% rename from android/src/main/java/io/ably/lib/push/PushChannel.java rename to core-android/src/main/java/io/ably/pubsub/push/PushChannel.java index 55b3a96d8..550ec6261 100644 --- a/android/src/main/java/io/ably/lib/push/PushChannel.java +++ b/core-android/src/main/java/io/ably/pubsub/push/PushChannel.java @@ -1,30 +1,30 @@ -package io.ably.lib.push; +package io.ably.pubsub.push; import com.google.gson.JsonObject; -import io.ably.lib.http.BasePaginatedQuery; -import io.ably.lib.http.Http; -import io.ably.lib.http.HttpCore; -import io.ably.lib.http.HttpScheduler; -import io.ably.lib.http.HttpUtils; -import io.ably.lib.realtime.CompletionListener; -import io.ably.lib.rest.AblyRest; -import io.ably.lib.rest.Channel; -import io.ably.lib.rest.DeviceDetails; -import io.ably.lib.types.AblyException; -import io.ably.lib.types.AsyncPaginatedResult; -import io.ably.lib.types.Callback; -import io.ably.lib.types.PaginatedResult; -import io.ably.lib.types.Param; -import io.ably.lib.util.ParamsUtils; +import io.ably.pubsub.http.BasePaginatedQuery; +import io.ably.pubsub.http.HttpRequester; +import io.ably.pubsub.http.HttpCore; +import io.ably.pubsub.http.HttpScheduler; +import io.ably.pubsub.http.HttpUtils; +import io.ably.pubsub.realtime.CompletionListener; +import io.ably.pubsub.http.PubSubHttpClient; +import io.ably.pubsub.http.Channel; +import io.ably.pubsub.http.DeviceDetails; +import io.ably.pubsub.types.AblyException; +import io.ably.pubsub.types.AsyncPaginatedResult; +import io.ably.pubsub.types.Callback; +import io.ably.pubsub.types.PaginatedResult; +import io.ably.pubsub.types.Param; +import io.ably.pubsub.util.ParamsUtils; /** * Enables devices to subscribe to push notifications for a channel. */ public class PushChannel { protected final Channel channel; - protected final AblyRest rest; + protected final PubSubHttpClient rest; - public PushChannel(Channel channel, AblyRest rest) { + public PushChannel(Channel channel, PubSubHttpClient rest) { this.channel = channel; this.rest = rest; } @@ -52,7 +52,7 @@ public void subscribeClientAsync(CompletionListener listener) { subscribeClientImpl().async(new CompletionListener.ToCallback<>(listener)); } - protected Http.Request subscribeClientImpl() { + protected HttpRequester.Request subscribeClientImpl() { JsonObject bodyJson = new JsonObject(); try { bodyJson.addProperty("clientId", getClientId()); @@ -86,7 +86,7 @@ public void subscribeDeviceAsync(CompletionListener listener) { subscribeDeviceImpl().async(new CompletionListener.ToCallback<>(listener)); } - protected Http.Request subscribeDeviceImpl() { + protected HttpRequester.Request subscribeDeviceImpl() { try { DeviceDetails device = getDevice(); JsonObject bodyJson = new JsonObject(); @@ -98,11 +98,11 @@ protected Http.Request subscribeDeviceImpl() { } } - protected Http.Request postSubscription(JsonObject bodyJson) { + protected HttpRequester.Request postSubscription(JsonObject bodyJson) { bodyJson.addProperty("channel", channel.name); final HttpCore.RequestBody body = HttpUtils.requestBodyFromGson(bodyJson, rest.options.useBinaryProtocol); - return rest.http.request(new Http.Execute() { + return rest.http.request(new HttpRequester.Execute() { @Override public void execute(HttpScheduler http, Callback callback) throws AblyException { Param[] params = ParamsUtils.enrichParams(null, rest.options); @@ -134,7 +134,7 @@ public void unsubscribeClientAsync(CompletionListener listener) { unsubscribeClientImpl().async(new CompletionListener.ToCallback<>(listener)); } - protected Http.Request unsubscribeClientImpl() { + protected HttpRequester.Request unsubscribeClientImpl() { try { Param[] params = new Param[] { new Param("channel", channel.name), new Param("clientId", getClientId()) }; return delSubscription(params); @@ -166,7 +166,7 @@ public void unsubscribeDeviceAsync(CompletionListener listener) { unsubscribeDeviceImpl().async(new CompletionListener.ToCallback<>(listener)); } - protected Http.Request unsubscribeDeviceImpl() { + protected HttpRequester.Request unsubscribeDeviceImpl() { try { DeviceDetails device = getDevice(); Param[] params = new Param[] { new Param("channel", channel.name), new Param("deviceId", device.id) }; @@ -176,9 +176,9 @@ protected Http.Request unsubscribeDeviceImpl() { } } - protected Http.Request delSubscription(Param[] params) { + protected HttpRequester.Request delSubscription(Param[] params) { final Param[] finalParams = ParamsUtils.enrichParams(params, rest.options); - return rest.http.request(new Http.Execute() { + return rest.http.request(new HttpRequester.Execute() { @Override public void execute(HttpScheduler http, Callback callback) throws AblyException { http.del("/push/channelSubscriptions", rest.push.pushRequestHeaders(true), finalParams, null, true, callback); @@ -257,7 +257,7 @@ protected DeviceDetails getDevice() throws AblyException { // Arguably that encourages just ignoring any errors, and forcing you to listen // to the broadcast after push.activate has finished before subscribing is // more robust. - throw AblyException.fromThrowable(new Exception("cannot use device before AblyRest.push.activate has finished")); + throw AblyException.fromThrowable(new Exception("cannot use device before PubSubHttpClient.push.activate has finished")); } return localDevice; } diff --git a/android/src/main/java/io/ably/lib/push/SharedPreferenceStorage.java b/core-android/src/main/java/io/ably/pubsub/push/SharedPreferenceStorage.java similarity index 97% rename from android/src/main/java/io/ably/lib/push/SharedPreferenceStorage.java rename to core-android/src/main/java/io/ably/pubsub/push/SharedPreferenceStorage.java index 6f2315ed8..d6626661a 100644 --- a/android/src/main/java/io/ably/lib/push/SharedPreferenceStorage.java +++ b/core-android/src/main/java/io/ably/pubsub/push/SharedPreferenceStorage.java @@ -1,4 +1,4 @@ -package io.ably.lib.push; +package io.ably.pubsub.push; import android.content.SharedPreferences; import android.preference.PreferenceManager; diff --git a/core-android/src/main/java/io/ably/pubsub/realtime/Channel.java b/core-android/src/main/java/io/ably/pubsub/realtime/Channel.java new file mode 100644 index 000000000..75f06f4b2 --- /dev/null +++ b/core-android/src/main/java/io/ably/pubsub/realtime/Channel.java @@ -0,0 +1,26 @@ +package io.ably.pubsub.realtime; + +import io.ably.pubsub.types.AblyException; +import io.ably.pubsub.types.ChannelOptions; +import io.ably.pubsub.push.PushChannel; +import io.ably.pubsub.liveobjects.LiveObjectsPlugin; + + +public class Channel extends ChannelBase { + /** + * A {@link PushChannel} object. + *

+ * Spec: RSH4 + */ + public final PushChannel push; + + Channel(PubSubRealtimeClient ably, String name, ChannelOptions options, LiveObjectsPlugin liveObjectsPlugin) throws AblyException { + super(ably, name, options, liveObjectsPlugin); + this.push = ((io.ably.pubsub.http.PubSubHttpClient) ably).channels.get(name, options).push; + } + + /** + * An interface whereby a client maybe notified of messages changes on a channel. + */ + public interface MessageListener extends ChannelBase.MessageListener {} +} diff --git a/android/src/main/java/io/ably/lib/types/RegistrationToken.java b/core-android/src/main/java/io/ably/pubsub/types/RegistrationToken.java similarity index 94% rename from android/src/main/java/io/ably/lib/types/RegistrationToken.java rename to core-android/src/main/java/io/ably/pubsub/types/RegistrationToken.java index 8b6981950..3d1e35eca 100644 --- a/android/src/main/java/io/ably/lib/types/RegistrationToken.java +++ b/core-android/src/main/java/io/ably/pubsub/types/RegistrationToken.java @@ -1,4 +1,4 @@ -package io.ably.lib.types; +package io.ably.pubsub.types; import java.util.Locale; @@ -12,7 +12,6 @@ public RegistrationToken(Type type, String token) { } public enum Type { - @Deprecated GCM, FCM; public static Type fromOrdinal(int i) { diff --git a/android/src/main/java/io/ably/lib/util/AndroidPlatformAgentProvider.java b/core-android/src/main/java/io/ably/pubsub/util/AndroidPlatformAgentProvider.java similarity index 89% rename from android/src/main/java/io/ably/lib/util/AndroidPlatformAgentProvider.java rename to core-android/src/main/java/io/ably/pubsub/util/AndroidPlatformAgentProvider.java index 000d858da..cb1436871 100644 --- a/android/src/main/java/io/ably/lib/util/AndroidPlatformAgentProvider.java +++ b/core-android/src/main/java/io/ably/pubsub/util/AndroidPlatformAgentProvider.java @@ -1,4 +1,4 @@ -package io.ably.lib.util; +package io.ably.pubsub.util; import android.os.Build; diff --git a/android/src/main/java/io/ably/lib/util/IntentUtils.java b/core-android/src/main/java/io/ably/pubsub/util/IntentUtils.java similarity index 91% rename from android/src/main/java/io/ably/lib/util/IntentUtils.java rename to core-android/src/main/java/io/ably/pubsub/util/IntentUtils.java index 3f3ec5fe6..a59197c3b 100644 --- a/android/src/main/java/io/ably/lib/util/IntentUtils.java +++ b/core-android/src/main/java/io/ably/pubsub/util/IntentUtils.java @@ -1,7 +1,7 @@ -package io.ably.lib.util; +package io.ably.pubsub.util; import android.content.Intent; -import io.ably.lib.types.ErrorInfo; +import io.ably.pubsub.types.ErrorInfo; public class IntentUtils { public static void addErrorInfo(Intent intent, ErrorInfo error) { diff --git a/android/src/main/resources/META-INF/io/ably/ably-android/verification.properties b/core-android/src/main/resources/META-INF/io/ably/ably-android/verification.properties similarity index 100% rename from android/src/main/resources/META-INF/io/ably/ably-android/verification.properties rename to core-android/src/main/resources/META-INF/io/ably/ably-android/verification.properties diff --git a/java/build.gradle.kts b/core/build.gradle.kts similarity index 89% rename from java/build.gradle.kts rename to core/build.gradle.kts index abef6f227..9ec4947b5 100644 --- a/java/build.gradle.kts +++ b/core/build.gradle.kts @@ -37,7 +37,7 @@ dependencies { buildConfig { useJavaOutput() - packageName = "io.ably.lib" + packageName = "io.ably.pubsub" buildConfigField("String", "LIBRARY_NAME", "\"java\"") buildConfigField("String", "VERSION", "\"${property("VERSION_NAME")}\"") } @@ -63,7 +63,7 @@ kotlin { } tasks.checkstyleMain.configure { - exclude("io/ably/lib/BuildConfig.java") + exclude("io/ably/pubsub/BuildConfig.java") } tasks.register("testRealtimeSuite") { @@ -85,9 +85,9 @@ tasks.register("testRealtimeSuite") { } } -tasks.register("testRestSuite") { +tasks.register("testHttpSuite") { filter { - includeTestsMatching("*RestSuite") + includeTestsMatching("*HttpSuite") } jvmArgs("--add-opens", "java.base/java.time=ALL-UNNAMED") jvmArgs("--add-opens", "java.base/java.lang=ALL-UNNAMED") @@ -109,13 +109,13 @@ tasks.register("testRestSuite") { /* Test task to run pure unit tests, where pure means that they only run locally and do not need to communicate with Ably servers. -This is achieved by excluding everything in the io.ably.lib.test package, +This is achieved by excluding everything in the io.ably.pubsub.test package, as it only contains the REST and Realtime suites. */ tasks.register("runUnitTests") { filter { - excludeTestsMatching("io.ably.lib.test.*") - excludeTestsMatching("io.ably.lib.uts.*") // UTS Jupiter suites run via runUts* tasks only + excludeTestsMatching("io.ably.pubsub.test.*") + excludeTestsMatching("io.ably.pubsub.uts.*") // UTS Jupiter suites run via runUts* tasks only } jvmArgs("--add-opens", "java.base/java.time=ALL-UNNAMED") jvmArgs("--add-opens", "java.base/java.lang=ALL-UNNAMED") @@ -126,7 +126,7 @@ tasks.register("runUnitTests") { tasks.register("runUtsUnitTests") { useJUnitPlatform() filter { - includeTestsMatching("io.ably.lib.uts.unit.*") + includeTestsMatching("io.ably.pubsub.uts.unit.*") } jvmArgs("--add-opens", "java.base/java.time=ALL-UNNAMED") jvmArgs("--add-opens", "java.base/java.lang=ALL-UNNAMED") @@ -137,7 +137,7 @@ tasks.register("runUtsUnitTests") { tasks.register("runUtsIntegrationTests") { useJUnitPlatform() filter { - includeTestsMatching("io.ably.lib.uts.integration.*") + includeTestsMatching("io.ably.pubsub.uts.integration.*") } jvmArgs("--add-opens", "java.base/java.time=ALL-UNNAMED") jvmArgs("--add-opens", "java.base/java.lang=ALL-UNNAMED") diff --git a/core/gradle.properties b/core/gradle.properties new file mode 100644 index 000000000..c315e84b2 --- /dev/null +++ b/core/gradle.properties @@ -0,0 +1,8 @@ +POM_ARTIFACT_ID=core +POM_NAME=Ably Pub/Sub core (JVM) +POM_DESCRIPTION=Internal implementation artifact for Ably's own Pub/Sub device/server packages. Not intended for direct use: depend on io.ably.pubsub:server (JVM) or io.ably.pubsub:device (Android) instead. +POM_PACKAGING=jar + +# The Kotlin plugin is applied for TEST-ONLY Kotlin sources; keep kotlin-stdlib out of :core's +# main scopes so it never enters the published io.ably.pubsub:core POM/runtime (Java-only artifact). +kotlin.stdlib.default.dependency=false diff --git a/core/src/main/java/io/ably/pubsub/http/Channel.java b/core/src/main/java/io/ably/pubsub/http/Channel.java new file mode 100644 index 000000000..89fd34163 --- /dev/null +++ b/core/src/main/java/io/ably/pubsub/http/Channel.java @@ -0,0 +1,10 @@ +package io.ably.pubsub.http; + +import io.ably.pubsub.types.AblyException; +import io.ably.pubsub.types.ChannelOptions; + +public class Channel extends ChannelBase { + Channel(PubSubBase ably, String name, ChannelOptions options) throws AblyException { + super(ably, name, options); + } +} diff --git a/core/src/main/java/io/ably/pubsub/http/PubSubHttpClient.java b/core/src/main/java/io/ably/pubsub/http/PubSubHttpClient.java new file mode 100644 index 000000000..33347e543 --- /dev/null +++ b/core/src/main/java/io/ably/pubsub/http/PubSubHttpClient.java @@ -0,0 +1,28 @@ +package io.ably.pubsub.http; + +import io.ably.pubsub.types.AblyException; +import io.ably.pubsub.types.ClientOptions; +import io.ably.pubsub.util.JavaPlatformAgentProvider; + +/** + * A client that offers a simple stateless API to interact directly with Ably's REST API. + * + * This class implements {@link AutoCloseable} so you can use it in + * try-with-resources constructs and have the JDK close it for you. + */ +public class PubSubHttpClient extends PubSubBase { + /** + * Construct a client object using an Ably {@link ClientOptions} object. + *

+ * Not public: a client is obtained from the builders of the {@code io.ably.pubsub:device} or + * {@code io.ably.pubsub:server} artifact, which name the side of the connection your code + * runs on. {@link HttpClientFactory} is the seam those builders construct through. + *

+ * Spec: RSC1 + * @param options A {@link ClientOptions} object to configure the client connection to Ably. + * @throws AblyException + */ + protected PubSubHttpClient(ClientOptions options) throws AblyException { + super(options, new JavaPlatformAgentProvider()); + } +} diff --git a/java/src/main/java/io/ably/lib/platform/Platform.java b/core/src/main/java/io/ably/pubsub/platform/Platform.java similarity index 78% rename from java/src/main/java/io/ably/lib/platform/Platform.java rename to core/src/main/java/io/ably/pubsub/platform/Platform.java index bf469aeb9..22159e75a 100644 --- a/java/src/main/java/io/ably/lib/platform/Platform.java +++ b/core/src/main/java/io/ably/pubsub/platform/Platform.java @@ -1,6 +1,6 @@ -package io.ably.lib.platform; +package io.ably.pubsub.platform; -import io.ably.lib.transport.NetworkConnectivity; +import io.ably.pubsub.transport.NetworkConnectivity; public class Platform { public static final String name = "java"; diff --git a/java/src/main/java/io/ably/lib/push/Push.java b/core/src/main/java/io/ably/pubsub/push/Push.java similarity index 61% rename from java/src/main/java/io/ably/lib/push/Push.java rename to core/src/main/java/io/ably/pubsub/push/Push.java index f9385a7c6..a5b501827 100644 --- a/java/src/main/java/io/ably/lib/push/Push.java +++ b/core/src/main/java/io/ably/pubsub/push/Push.java @@ -1,12 +1,12 @@ -package io.ably.lib.push; +package io.ably.pubsub.push; -import io.ably.lib.rest.AblyBase; +import io.ably.pubsub.http.PubSubBase; /** * Enables a device to be registered and deregistered from receiving push notifications. */ public class Push extends PushBase { - public Push(AblyBase rest) { + public Push(PubSubBase rest) { super(rest); } } diff --git a/core/src/main/java/io/ably/pubsub/realtime/Channel.java b/core/src/main/java/io/ably/pubsub/realtime/Channel.java new file mode 100644 index 000000000..07352db02 --- /dev/null +++ b/core/src/main/java/io/ably/pubsub/realtime/Channel.java @@ -0,0 +1,14 @@ +package io.ably.pubsub.realtime; + +import io.ably.pubsub.liveobjects.LiveObjectsPlugin; +import io.ably.pubsub.types.AblyException; +import io.ably.pubsub.types.ChannelOptions; +import org.jetbrains.annotations.Nullable; + +public class Channel extends ChannelBase { + Channel(PubSubRealtimeClient ably, String name, ChannelOptions options, @Nullable LiveObjectsPlugin liveObjectsPlugin) throws AblyException { + super(ably, name, options, liveObjectsPlugin); + } + + public interface MessageListener extends ChannelBase.MessageListener {} +} diff --git a/java/src/main/java/io/ably/lib/util/JavaPlatformAgentProvider.java b/core/src/main/java/io/ably/pubsub/util/JavaPlatformAgentProvider.java similarity index 93% rename from java/src/main/java/io/ably/lib/util/JavaPlatformAgentProvider.java rename to core/src/main/java/io/ably/pubsub/util/JavaPlatformAgentProvider.java index c4b415d56..dfd06e942 100644 --- a/java/src/main/java/io/ably/lib/util/JavaPlatformAgentProvider.java +++ b/core/src/main/java/io/ably/pubsub/util/JavaPlatformAgentProvider.java @@ -1,4 +1,4 @@ -package io.ably.lib.util; +package io.ably.pubsub.util; public class JavaPlatformAgentProvider implements PlatformAgentProvider { @Override diff --git a/java/src/test/java/io/ably/lib/test/loader/ArgumentLoader.java b/core/src/test/java/io/ably/pubsub/test/loader/ArgumentLoader.java similarity index 77% rename from java/src/test/java/io/ably/lib/test/loader/ArgumentLoader.java rename to core/src/test/java/io/ably/pubsub/test/loader/ArgumentLoader.java index 241db394b..62b2d7392 100644 --- a/java/src/test/java/io/ably/lib/test/loader/ArgumentLoader.java +++ b/core/src/test/java/io/ably/pubsub/test/loader/ArgumentLoader.java @@ -1,4 +1,4 @@ -package io.ably.lib.test.loader; +package io.ably.pubsub.test.loader; public class ArgumentLoader { public String getTestArgument(String name) { diff --git a/java/src/test/java/io/ably/lib/test/loader/ResourceLoader.java b/core/src/test/java/io/ably/pubsub/test/loader/ResourceLoader.java similarity index 96% rename from java/src/test/java/io/ably/lib/test/loader/ResourceLoader.java rename to core/src/test/java/io/ably/pubsub/test/loader/ResourceLoader.java index df06dd5c1..e65482538 100644 --- a/java/src/test/java/io/ably/lib/test/loader/ResourceLoader.java +++ b/core/src/test/java/io/ably/pubsub/test/loader/ResourceLoader.java @@ -1,4 +1,4 @@ -package io.ably.lib.test.loader; +package io.ably.pubsub.test.loader; import java.io.File; import java.io.FileInputStream; diff --git a/deploy/check-archives.sh b/deploy/check-archives.sh index 7914caedd..2a3d14c19 100755 --- a/deploy/check-archives.sh +++ b/deploy/check-archives.sh @@ -36,8 +36,8 @@ case "${ABLY_VERSION}" in ;; esac -ABLY_JAVA_RELEASE_DIR="${ABLY_HOME}/java/build/release/${ABLY_VERSION}/io/ably/ably-java/${ABLY_VERSION}" -ABLY_ANDROID_RELEASE_DIR="${ABLY_HOME}/android/build/release/${ABLY_VERSION}/io/ably/ably-android/${ABLY_VERSION}" +ABLY_JAVA_RELEASE_DIR="${ABLY_HOME}/core/build/release/${ABLY_VERSION}/io/ably/ably-java/${ABLY_VERSION}" +ABLY_ANDROID_RELEASE_DIR="${ABLY_HOME}/core-android/build/release/${ABLY_VERSION}/io/ably/ably-android/${ABLY_VERSION}" if [ ! -d "${ABLY_JAVA_RELEASE_DIR}" ]; then echo "Directory for Java release ${ABLY_JAVA_RELEASE_DIR} doesn't exist" diff --git a/device/build.gradle.kts b/device/build.gradle.kts new file mode 100644 index 000000000..3e39647ed --- /dev/null +++ b/device/build.gradle.kts @@ -0,0 +1,101 @@ +import com.vanniktech.maven.publish.JavadocJar +import com.vanniktech.maven.publish.KotlinMultiplatform +import org.jetbrains.kotlin.gradle.dsl.JvmTarget + +plugins { + alias(libs.plugins.kotlin.multiplatform) + alias(libs.plugins.android.library) + alias(libs.plugins.maven.publish) +} + +kotlin { + explicitApi() + + androidTarget { + compilerOptions { + jvmTarget.set(JvmTarget.JVM_1_8) + } + publishLibraryVariants("release") + } + + jvm { + compilerOptions { + jvmTarget.set(JvmTarget.JVM_1_8) + } + } + + sourceSets { + commonMain.dependencies { + /* + * The two platform artifacts publish the same io.ably.pubsub.* types, so common code + * compiles against either one. ably-java is the arbitrary pick; each target below + * brings the real one. + */ + compileOnly(project(":core")) + } + androidMain.dependencies { + api(project(":core-android")) + } + jvmMain.dependencies { + api(project(":core")) + } + commonTest.dependencies { + compileOnly(project(":core")) + implementation(kotlin("test")) + } + } +} + +android { + namespace = "io.ably.pubsub.device" + compileSdk = 34 + + defaultConfig { + minSdk = 24 + testInstrumentationRunner = "android.support.test.runner.AndroidJUnitRunner" + } + + compileOptions { + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + } + + buildTypes { + getByName("release") { + isMinifyEnabled = false + } + } + + lint { + abortOnError = false + } + + testOptions { + targetSdk = 34 + /* + * AndroidPlatformAgentProvider reads android.os.Build.VERSION.SDK_INT, which is an unmocked + * stub in local unit tests. Without this it throws instead of returning a default. + */ + unitTests.isReturnDefaultValues = true + } +} + +dependencies { + /* + * The instrumentation test is Java under src/androidTest/java, so AGP compiles it rather + * than a Kotlin source set and its dependencies belong on AGP's androidTest configuration. + * It needs only JUnit and a runner: unlike :core-android's push tests it mocks nothing, so + * the instrumental-android bundle (dexmaker, mockito, retrostreams) would be dead weight. + */ + androidTestImplementation(libs.junit) + androidTestImplementation(libs.android.test.runner) +} + +mavenPublishing { + configure(KotlinMultiplatform(javadocJar = JavadocJar.Empty(), androidVariantsToPublish = listOf("release"))) +} + +/* check.yml invokes `runUnitTests` unqualified across all projects. */ +tasks.register("runUnitTests") { + dependsOn("jvmTest", "testDebugUnitTest") +} diff --git a/device/gradle.properties b/device/gradle.properties new file mode 100644 index 000000000..f4c3d8242 --- /dev/null +++ b/device/gradle.properties @@ -0,0 +1,3 @@ +POM_ARTIFACT_ID=device +POM_NAME=Ably Pub/Sub device SDK +POM_DESCRIPTION=Ably Pub/Sub SDK for applications running on end-user devices, for Android and the JVM. diff --git a/device/src/androidMain/AndroidManifest.xml b/device/src/androidMain/AndroidManifest.xml new file mode 100644 index 000000000..a2f47b605 --- /dev/null +++ b/device/src/androidMain/AndroidManifest.xml @@ -0,0 +1,2 @@ + + diff --git a/device/src/androidTest/java/io/ably/pubsub/device/PubSubDeviceTest.java b/device/src/androidTest/java/io/ably/pubsub/device/PubSubDeviceTest.java new file mode 100644 index 000000000..0a1509079 --- /dev/null +++ b/device/src/androidTest/java/io/ably/pubsub/device/PubSubDeviceTest.java @@ -0,0 +1,78 @@ +package io.ably.pubsub.device; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotSame; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +import io.ably.pubsub.realtime.PubSubRealtimeClient; +import io.ably.pubsub.types.ClientOptions; +import io.ably.pubsub.util.Side; +import java.util.HashMap; +import java.util.Map; +import org.junit.Test; + +/** + * The agent entries asserted here are what the platform reads to classify traffic on + * MAU-priced accounts, so these tests are deliberately strict: if one fails, billing + * classification is broken, not just a header. + *

+ * The side entry is a versionless flag — a bare token on the wire, registered as such in the ably-common agents registry + * — so the assertions also fail if a version (or any {@code /suffix}) reappears on it. + */ +public class PubSubDeviceTest { + + private static final String FAKE_KEY = "fakeAppId.fakeKeyId:fakeKeySecret"; + + private static ClientOptions offlineOptions(String key) throws Exception { + ClientOptions options = new ClientOptions(key); + options.autoConnect = false; + return options; + } + + /** The stamped entry is present as a versionless flag, and the other side's is absent. */ + private static void assertDeviceFlag(Map agents) { + assertTrue("expected the device side flag", agents.containsKey(Side.DEVICE_AGENT_IDENTIFIER)); + assertNull("the side flag is versionless", agents.get(Side.DEVICE_AGENT_IDENTIFIER)); + assertFalse("a device client must not carry the server entry", + agents.containsKey(Side.SERVER_AGENT_IDENTIFIER)); + } + + @Test + public void client_stampsDeviceAgent() throws Exception { + PubSubRealtimeClient client = PubSubDevice.clientBuilder(offlineOptions(FAKE_KEY)).build(); + assertDeviceFlag(client.options.agents); + } + + @Test + public void key_isCarriedThroughToTheClient() throws Exception { + ClientOptions builtOptions = PubSubDevice.clientBuilder() + .key(FAKE_KEY) + .autoConnect(false) + .build() + .options; + assertEquals(FAKE_KEY, builtOptions.key); + assertNull(builtOptions.token); + assertDeviceFlag(builtOptions.agents); + } + + @Test + public void callerAgentEntries_arePreserved_andCannotOverrideTheSideEntry() throws Exception { + ClientOptions options = offlineOptions(FAKE_KEY); + Map callerAgents = new HashMap<>(); + callerAgents.put("some-sdk", "1.2.3"); + callerAgents.put(Side.DEVICE_AGENT_IDENTIFIER, "not-the-real-form"); + options.agents = callerAgents; + + PubSubRealtimeClient client = PubSubDevice.clientBuilder(options).build(); + assertEquals("1.2.3", client.options.agents.get("some-sdk")); + // The stamp replaces the caller's value: the flag is present and back to versionless. + assertDeviceFlag(client.options.agents); + + // the caller's own map is untouched: the stamp goes into a fresh one + assertNotSame("the stamp must go into a copy, not the caller's map", + callerAgents, client.options.agents); + assertEquals("not-the-real-form", callerAgents.get(Side.DEVICE_AGENT_IDENTIFIER)); + } +} diff --git a/device/src/commonMain/kotlin/io/ably/pubsub/device/PubSubDevice.kt b/device/src/commonMain/kotlin/io/ably/pubsub/device/PubSubDevice.kt new file mode 100644 index 000000000..84d47ba71 --- /dev/null +++ b/device/src/commonMain/kotlin/io/ably/pubsub/device/PubSubDevice.kt @@ -0,0 +1,421 @@ +package io.ably.pubsub.device + +import io.ably.pubsub.push.Storage +import io.ably.pubsub.realtime.PubSubRealtimeClient +import io.ably.pubsub.realtime.RealtimeClientFactory +import io.ably.pubsub.http.Auth +import io.ably.pubsub.types.ClientOptions +import io.ably.pubsub.types.Param +import io.ably.pubsub.types.ProxyOptions +import io.ably.pubsub.util.Log +import io.ably.pubsub.util.Side + +/** + * Entry point for the Ably Pub/Sub SDK for devices: applications running on end-user devices, whose + * connections are counted on accounts with monthly-active-user billing. + * + * Clients built here are the same [PubSubRealtimeClient] objects the core SDK has always returned, and + * behave identically. What the artifact adds is the choice itself: the dependency you declare and + * the factory you call state which side of the connection your code runs on, rather than leaving it + * to be inferred. + * + * If your code runs on infrastructure you control, use the `io.ably.pubsub:server` artifact instead. + * + * There is a single door because there is a single choice to make. Connectionless operations — + * history, presence queries, token requests, `request()` and `batchPublish()` — are all available on + * the client this returns. + * + * ``` + * val client = PubSubDevice.clientBuilder() + * .key("xVLyHw.MHOCLg:...") + * .clientId("bob") + * .build() + * ``` + */ +public object PubSubDevice { + + /** + * Creates a builder for a device client. It exposes one method per [ClientOptions] property. + * + * @return a new builder. + */ + @JvmStatic + public fun clientBuilder(): ClientBuilder = ClientBuilder() + + /** + * As [clientBuilder], but starting from options the caller has already assembled, rather + * than from the builder's own empty set. + * + * This is for callers holding a [ClientOptions] they did not build here: an SDK layered on + * this package that takes options from its own user, or a test harness passing a + * [io.ably.pubsub.debug.DebugOptions] subclass. To supply an API key or token, prefer + * [ClientBuilder.key] or [ClientBuilder.token] on the no-arg builder over assembling + * options for it. + * + * The builder's setters still apply on top of what is passed here, and [ClientBuilder.build] + * stamps the side-declaring agent entry as usual. The options object is handed to the + * client rather than copied, so later changes to it are not isolated from the built client, + * and [ClientBuilder.build] replaces its `agents` map with the stamped one; pass + * [ClientOptions.copy] if either matters. + * + * @param options the options to start from. + * @return a new builder over [options]. + */ + @JvmStatic + public fun clientBuilder(options: ClientOptions): ClientBuilder = ClientBuilder(options) + + /** + * Builds a device client. Obtain one from [PubSubDevice.clientBuilder]. + */ + public class ClientBuilder internal constructor( + /** Accumulates the calls made on this builder; handed to the client as-is by [build]. */ + private val options: ClientOptions = ClientOptions(), + ) { + + /** + * Sets [Auth.AuthOptions.authCallback]. + * + * @param authCallback the value to set. + * @return this builder. + */ + public fun authCallback(authCallback: Auth.TokenCallback): ClientBuilder = apply { options.authCallback = authCallback } + + /** + * Sets [Auth.AuthOptions.authUrl]. + * + * @param authUrl the value to set. + * @return this builder. + */ + public fun authUrl(authUrl: String): ClientBuilder = apply { options.authUrl = authUrl } + + /** + * Sets [Auth.AuthOptions.authMethod]. + * + * @param authMethod the value to set. + * @return this builder. + */ + public fun authMethod(authMethod: String): ClientBuilder = apply { options.authMethod = authMethod } + + /** + * Sets [Auth.AuthOptions.key]. + * + * @param key the value to set. + * @return this builder. + */ + public fun key(key: String): ClientBuilder = apply { options.key = key } + + /** + * Sets [Auth.AuthOptions.token]. + * + * @param token the value to set. + * @return this builder. + */ + public fun token(token: String): ClientBuilder = apply { options.token = token } + + /** + * Sets [Auth.AuthOptions.tokenDetails]. + * + * @param tokenDetails the value to set. + * @return this builder. + */ + public fun tokenDetails(tokenDetails: Auth.TokenDetails): ClientBuilder = apply { options.tokenDetails = tokenDetails } + + /** + * Sets [Auth.AuthOptions.authHeaders]. + * + * @param authHeaders the value to set. + * @return this builder. + */ + public fun authHeaders(authHeaders: Array): ClientBuilder = apply { options.authHeaders = authHeaders } + + /** + * Sets [Auth.AuthOptions.authParams]. + * + * @param authParams the value to set. + * @return this builder. + */ + public fun authParams(authParams: Array): ClientBuilder = apply { options.authParams = authParams } + + /** + * Sets [Auth.AuthOptions.queryTime]. + * + * @param queryTime the value to set. + * @return this builder. + */ + public fun queryTime(queryTime: Boolean): ClientBuilder = apply { options.queryTime = queryTime } + + /** + * Sets [Auth.AuthOptions.useTokenAuth]. + * + * @param useTokenAuth the value to set. + * @return this builder. + */ + public fun useTokenAuth(useTokenAuth: Boolean): ClientBuilder = apply { options.useTokenAuth = useTokenAuth } + + /** + * Sets [ClientOptions.clientId]. + * + * @param clientId the value to set. + * @return this builder. + */ + public fun clientId(clientId: String): ClientBuilder = apply { options.clientId = clientId } + + /** + * Sets [ClientOptions.logLevel]. + * + * @param logLevel the value to set. + * @return this builder. + */ + public fun logLevel(logLevel: Int): ClientBuilder = apply { options.logLevel = logLevel } + + /** + * Sets [ClientOptions.logHandler]. + * + * @param logHandler the value to set. + * @return this builder. + */ + public fun logHandler(logHandler: Log.LogHandler): ClientBuilder = apply { options.logHandler = logHandler } + + /** + * Sets [ClientOptions.tls]. + * + * @param tls the value to set. + * @return this builder. + */ + public fun tls(tls: Boolean): ClientBuilder = apply { options.tls = tls } + + /** + * Sets [ClientOptions.headers]. + * + * @param headers the value to set. + * @return this builder. + */ + public fun headers(headers: Map): ClientBuilder = apply { options.headers = headers } + + /** + * Sets [ClientOptions.endpoint]. + * + * @param endpoint the value to set. + * @return this builder. + */ + public fun endpoint(endpoint: String): ClientBuilder = apply { options.endpoint = endpoint } + + /** + * Sets [ClientOptions.port]. + * + * @param port the value to set. + * @return this builder. + */ + public fun port(port: Int): ClientBuilder = apply { options.port = port } + + /** + * Sets [ClientOptions.tlsPort]. + * + * @param tlsPort the value to set. + * @return this builder. + */ + public fun tlsPort(tlsPort: Int): ClientBuilder = apply { options.tlsPort = tlsPort } + + /** + * Sets [ClientOptions.useBinaryProtocol]. + * + * @param useBinaryProtocol the value to set. + * @return this builder. + */ + public fun useBinaryProtocol(useBinaryProtocol: Boolean): ClientBuilder = apply { options.useBinaryProtocol = useBinaryProtocol } + + /** + * Sets [ClientOptions.proxy]. + * + * @param proxy the value to set. + * @return this builder. + */ + public fun proxy(proxy: ProxyOptions): ClientBuilder = apply { options.proxy = proxy } + + /** + * Sets [ClientOptions.idempotentRestPublishing]. + * + * @param idempotentRestPublishing the value to set. + * @return this builder. + */ + public fun idempotentRestPublishing(idempotentRestPublishing: Boolean): ClientBuilder = apply { options.idempotentRestPublishing = idempotentRestPublishing } + + /** + * Sets [ClientOptions.httpOpenTimeout]. + * + * @param httpOpenTimeout the value to set. + * @return this builder. + */ + public fun httpOpenTimeout(httpOpenTimeout: Int): ClientBuilder = apply { options.httpOpenTimeout = httpOpenTimeout } + + /** + * Sets [ClientOptions.httpRequestTimeout]. + * + * @param httpRequestTimeout the value to set. + * @return this builder. + */ + public fun httpRequestTimeout(httpRequestTimeout: Int): ClientBuilder = apply { options.httpRequestTimeout = httpRequestTimeout } + + /** + * Sets [ClientOptions.httpMaxRetryDuration]. + * + * @param httpMaxRetryDuration the value to set. + * @return this builder. + */ + public fun httpMaxRetryDuration(httpMaxRetryDuration: Int): ClientBuilder = apply { options.httpMaxRetryDuration = httpMaxRetryDuration } + + /** + * Sets [ClientOptions.httpMaxRetryCount]. + * + * @param httpMaxRetryCount the value to set. + * @return this builder. + */ + public fun httpMaxRetryCount(httpMaxRetryCount: Int): ClientBuilder = apply { options.httpMaxRetryCount = httpMaxRetryCount } + + /** + * Sets [ClientOptions.fallbackHosts]. + * + * @param fallbackHosts the value to set. + * @return this builder. + */ + public fun fallbackHosts(fallbackHosts: Array): ClientBuilder = apply { options.fallbackHosts = fallbackHosts } + + /** + * Sets [ClientOptions.fallbackRetryTimeout]. + * + * @param fallbackRetryTimeout the value to set. + * @return this builder. + */ + public fun fallbackRetryTimeout(fallbackRetryTimeout: Long): ClientBuilder = apply { options.fallbackRetryTimeout = fallbackRetryTimeout } + + /** + * Sets [ClientOptions.defaultTokenParams]. + * + * @param defaultTokenParams the value to set. + * @return this builder. + */ + public fun defaultTokenParams(defaultTokenParams: Auth.TokenParams): ClientBuilder = apply { options.defaultTokenParams = defaultTokenParams } + + /** + * Sets [ClientOptions.asyncHttpThreadpoolSize]. + * + * @param asyncHttpThreadpoolSize the value to set. + * @return this builder. + */ + public fun asyncHttpThreadpoolSize(asyncHttpThreadpoolSize: Int): ClientBuilder = apply { options.asyncHttpThreadpoolSize = asyncHttpThreadpoolSize } + + /** + * Sets [ClientOptions.pushFullWait]. + * + * @param pushFullWait the value to set. + * @return this builder. + */ + public fun pushFullWait(pushFullWait: Boolean): ClientBuilder = apply { options.pushFullWait = pushFullWait } + + /** + * Sets [ClientOptions.localStorage]. + * + * @param localStorage the value to set. + * @return this builder. + */ + public fun localStorage(localStorage: Storage): ClientBuilder = apply { options.localStorage = localStorage } + + /** + * Sets [ClientOptions.addRequestIds]. + * + * @param addRequestIds the value to set. + * @return this builder. + */ + public fun addRequestIds(addRequestIds: Boolean): ClientBuilder = apply { options.addRequestIds = addRequestIds } + + /** + * Sets [ClientOptions.agents]. + * + * @param agents the value to set. + * @return this builder. + */ + public fun agents(agents: Map): ClientBuilder = apply { options.agents = agents } + + /** + * Sets [ClientOptions.autoConnect]. + * + * @param autoConnect the value to set. + * @return this builder. + */ + public fun autoConnect(autoConnect: Boolean): ClientBuilder = apply { options.autoConnect = autoConnect } + + /** + * Sets [ClientOptions.queueMessages]. + * + * @param queueMessages the value to set. + * @return this builder. + */ + public fun queueMessages(queueMessages: Boolean): ClientBuilder = apply { options.queueMessages = queueMessages } + + /** + * Sets [ClientOptions.echoMessages]. + * + * @param echoMessages the value to set. + * @return this builder. + */ + public fun echoMessages(echoMessages: Boolean): ClientBuilder = apply { options.echoMessages = echoMessages } + + /** + * Sets [ClientOptions.recover]. + * + * @param recover the value to set. + * @return this builder. + */ + public fun recover(recover: String): ClientBuilder = apply { options.recover = recover } + + /** + * Sets [ClientOptions.realtimeRequestTimeout]. + * + * @param realtimeRequestTimeout the value to set. + * @return this builder. + */ + public fun realtimeRequestTimeout(realtimeRequestTimeout: Long): ClientBuilder = apply { options.realtimeRequestTimeout = realtimeRequestTimeout } + + /** + * Sets [ClientOptions.disconnectedRetryTimeout]. + * + * @param disconnectedRetryTimeout the value to set. + * @return this builder. + */ + public fun disconnectedRetryTimeout(disconnectedRetryTimeout: Long): ClientBuilder = apply { options.disconnectedRetryTimeout = disconnectedRetryTimeout } + + /** + * Sets [ClientOptions.suspendedRetryTimeout]. + * + * @param suspendedRetryTimeout the value to set. + * @return this builder. + */ + public fun suspendedRetryTimeout(suspendedRetryTimeout: Long): ClientBuilder = apply { options.suspendedRetryTimeout = suspendedRetryTimeout } + + /** + * Sets [ClientOptions.channelRetryTimeout]. + * + * @param channelRetryTimeout the value to set. + * @return this builder. + */ + public fun channelRetryTimeout(channelRetryTimeout: Int): ClientBuilder = apply { options.channelRetryTimeout = channelRetryTimeout } + + /** + * Sets [ClientOptions.transportParams]. + * + * @param transportParams the value to set. + * @return this builder. + */ + public fun transportParams(transportParams: Array): ClientBuilder = apply { options.transportParams = transportParams } + + /** + * Builds the client, which connects immediately unless [autoConnect] was set to false. + * + * @return an [PubSubRealtimeClient]. + * @throws io.ably.pubsub.types.AblyException if the options are invalid, for example if no + * authentication parameters were supplied. + */ + public fun build(): PubSubRealtimeClient = + RealtimeClientFactory.create(Side.injectSideAgent(options, Side.DEVICE_AGENT_IDENTIFIER)) + } +} diff --git a/device/src/commonTest/kotlin/io/ably/pubsub/device/PubSubDeviceTest.kt b/device/src/commonTest/kotlin/io/ably/pubsub/device/PubSubDeviceTest.kt new file mode 100644 index 000000000..5c9718644 --- /dev/null +++ b/device/src/commonTest/kotlin/io/ably/pubsub/device/PubSubDeviceTest.kt @@ -0,0 +1,62 @@ +package io.ably.pubsub.device + +import io.ably.pubsub.util.Side +import org.junit.Assert +import org.junit.Test + +/** + * The agent entries asserted here are what the platform reads to classify traffic on + * MAU-priced accounts, so these tests are deliberately strict: if one fails, billing + * classification is broken, not just a header. + * + * + * The side entry is a versionless flag — a bare token on the wire, registered as such in the ably-common agents registry + * — so the assertions also fail if a version (or any `/suffix`) reappears on it. + */ +class PubSubDeviceTest { + @Test + @Throws(Exception::class) + fun client_stampsDeviceAgent() { + val client = PubSubDevice.clientBuilder().key(FAKE_KEY).autoConnect(false).build() + assertDeviceFlag(client.options.agents) + } + + @Test + @Throws(Exception::class) + fun keyString_isAcceptedAndDisambiguatedAsKey() { + val builtOptions = PubSubDevice.clientBuilder().key(FAKE_KEY).autoConnect(false).build().options + Assert.assertEquals(FAKE_KEY, builtOptions.key) + Assert.assertNull(builtOptions.token) + assertDeviceFlag(builtOptions.agents) + } + + @Test + @Throws(Exception::class) + fun callerAgentEntries_arePreserved_andCannotOverrideTheSideEntry() { + val callerAgents: Map = mapOf( + "some-sdk" to "1.2.3", + Side.DEVICE_AGENT_IDENTIFIER to "not-the-real-form", + ) + + val client = PubSubDevice.clientBuilder().key(FAKE_KEY).autoConnect(false).agents(callerAgents).build() + Assert.assertEquals("1.2.3", client.options.agents.get("some-sdk")) + // The stamp replaces the caller's value: the flag is present and back to versionless. + assertDeviceFlag(client.options.agents) + + Assert.assertEquals("not-the-real-form", callerAgents.get(Side.DEVICE_AGENT_IDENTIFIER)) + } + + companion object { + private const val FAKE_KEY = "fakeAppId.fakeKeyId:fakeKeySecret" + + /** The stamped entry is present as a versionless flag, and the other side's is absent. */ + private fun assertDeviceFlag(agents: MutableMap) { + Assert.assertTrue("expected the device side flag", agents.containsKey(Side.DEVICE_AGENT_IDENTIFIER)) + Assert.assertNull("the side flag is versionless", agents.get(Side.DEVICE_AGENT_IDENTIFIER)) + Assert.assertFalse( + "a device client must not carry the server entry", + agents.containsKey(Side.SERVER_AGENT_IDENTIFIER) + ) + } + } +} diff --git a/examples/build.gradle.kts b/examples/build.gradle.kts index f9c566cf6..a5a2865f9 100644 --- a/examples/build.gradle.kts +++ b/examples/build.gradle.kts @@ -68,7 +68,9 @@ dependencies { implementation(libs.ktor.client.cio) implementation(project(":liveobjects")) - implementation(project(":android")) + implementation(project(":core-android")) + // The device door: this sample app runs on an end-user device, so it builds its clients here. + implementation(project(":device")) implementation(libs.navigation.compose) diff --git a/examples/src/androidTest/kotlin/com/ably/example/ColorVotingScreenTest.kt b/examples/src/androidTest/kotlin/com/ably/example/ColorVotingScreenTest.kt index f6651e298..2a097592f 100644 --- a/examples/src/androidTest/kotlin/com/ably/example/ColorVotingScreenTest.kt +++ b/examples/src/androidTest/kotlin/com/ably/example/ColorVotingScreenTest.kt @@ -1,9 +1,7 @@ package com.ably.example import androidx.compose.ui.semantics.SemanticsProperties -import androidx.compose.ui.test.assertIsDisplayed import androidx.compose.ui.test.junit4.createAndroidComposeRule -import androidx.compose.ui.test.onAllNodesWithText import androidx.compose.ui.test.onNodeWithTag import androidx.compose.ui.test.onNodeWithText import androidx.compose.ui.test.performClick diff --git a/examples/src/main/kotlin/com/ably/example/MainActivity.kt b/examples/src/main/kotlin/com/ably/example/MainActivity.kt index aad0d93e4..ffdbeda08 100644 --- a/examples/src/main/kotlin/com/ably/example/MainActivity.kt +++ b/examples/src/main/kotlin/com/ably/example/MainActivity.kt @@ -6,36 +6,41 @@ import androidx.activity.compose.setContent import androidx.activity.enableEdgeToEdge import com.ably.example.screen.MainScreen import com.ably.example.ui.theme.AblyTheme -import io.ably.lib.realtime.AblyRealtime -import io.ably.lib.rest.AblyRest -import io.ably.lib.rest.Auth -import io.ably.lib.types.ClientOptions -import io.ably.lib.util.Log +import io.ably.pubsub.device.PubSubDevice +import io.ably.pubsub.realtime.PubSubRealtimeClient +import io.ably.pubsub.http.Auth +import io.ably.pubsub.util.Log import kotlinx.coroutines.runBlocking class MainActivity : ComponentActivity() { - private val realtimeClient: AblyRealtime by lazy { - AblyRealtime( - ClientOptions().apply { + private val realtimeClient: PubSubRealtimeClient by lazy { + // This app runs on an end-user device, so it builds its client through the device door. + PubSubDevice.clientBuilder() + .apply { if (BuildConfig.ABLY_KEY.isBlank()) { - authCallback = Auth.TokenCallback { - val apiKey = runBlocking { - val sandbox = Sandbox.getInstance() - sandbox.apiKey + authCallback( + Auth.TokenCallback { + val apiKey = runBlocking { + val sandbox = Sandbox.getInstance() + sandbox.apiKey + } + // A throwaway client that only signs a token; it never connects. + PubSubDevice.clientBuilder() + .key(apiKey) + .endpoint("nonprod:sandbox") + .autoConnect(false) + .build() + .use { it.auth.requestToken(null, null) } } - AblyRest(ClientOptions().apply { - key = apiKey - environment = "sandbox" - }).auth.requestToken(null, null) - } - environment = "sandbox" + ) + endpoint("nonprod:sandbox") } else { - key = BuildConfig.ABLY_KEY + key(BuildConfig.ABLY_KEY) } - logLevel = Log.VERBOSE - autoConnect = false + logLevel(Log.VERBOSE) + autoConnect(false) } - ) + .build() } override fun onCreate(savedInstanceState: Bundle?) { diff --git a/examples/src/main/kotlin/com/ably/example/Utils.kt b/examples/src/main/kotlin/com/ably/example/Utils.kt index 2a8c20c2b..97bff04d8 100644 --- a/examples/src/main/kotlin/com/ably/example/Utils.kt +++ b/examples/src/main/kotlin/com/ably/example/Utils.kt @@ -1,13 +1,13 @@ /** * The LiveObjects bridge layer for the example app: Compose observers plus coroutine - * wrappers over the path-based API (`io.ably.lib.liveobjects`). + * wrappers over the path-based API (`io.ably.pubsub.liveobjects`). * - * The app works exclusively with [io.ably.lib.liveobjects.path.PathObject]s — references + * The app works exclusively with [io.ably.pubsub.liveobjects.path.PathObject]s — references * to a *location* in the channel's objects graph, not to a particular object. A PathObject * resolves its path lazily on every call, so a stored reference stays valid even when the * object at that location is replaced (e.g. "Reset all" swaps in brand-new counters), and * a path subscription automatically observes whatever object currently lives there. The - * identity-bound alternative, [io.ably.lib.liveobjects.instance.Instance] (obtained via + * identity-bound alternative, [io.ably.pubsub.liveobjects.instance.Instance] (obtained via * `pathObject.instance()`), tracks one specific object wherever it moves — not needed here, * since every screen wants location semantics. * @@ -27,19 +27,19 @@ import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue -import io.ably.lib.liveobjects.ValueType -import io.ably.lib.liveobjects.path.types.LiveCounterPathObject -import io.ably.lib.liveobjects.path.types.LiveMapPathObject -import io.ably.lib.liveobjects.state.ObjectStateEvent -import io.ably.lib.liveobjects.value.LiveCounter -import io.ably.lib.liveobjects.value.LiveMap -import io.ably.lib.liveobjects.value.LiveMapValue -import io.ably.lib.realtime.AblyRealtime -import io.ably.lib.realtime.Channel -import io.ably.lib.realtime.ChannelState -import io.ably.lib.realtime.ChannelStateListener -import io.ably.lib.types.ChannelMode -import io.ably.lib.types.ChannelOptions +import io.ably.pubsub.liveobjects.ValueType +import io.ably.pubsub.liveobjects.path.types.LiveCounterPathObject +import io.ably.pubsub.liveobjects.path.types.LiveMapPathObject +import io.ably.pubsub.liveobjects.state.ObjectStateEvent +import io.ably.pubsub.liveobjects.value.LiveCounter +import io.ably.pubsub.liveobjects.value.LiveMap +import io.ably.pubsub.liveobjects.value.LiveMapValue +import io.ably.pubsub.realtime.PubSubRealtimeClient +import io.ably.pubsub.realtime.Channel +import io.ably.pubsub.realtime.ChannelState +import io.ably.pubsub.realtime.ChannelStateListener +import io.ably.pubsub.types.ChannelMode +import io.ably.pubsub.types.ChannelOptions import kotlinx.coroutines.future.await /** @@ -207,7 +207,7 @@ fun observeRootObject(channel: Channel): LiveMapPathObject? { } @Composable -fun getRealtimeChannel(realtimeClient: AblyRealtime, channelName: String): Channel { +fun getRealtimeChannel(realtimeClient: PubSubRealtimeClient, channelName: String): Channel { val channel = realtimeClient.channels.get(channelName) DisposableEffect(channel) { diff --git a/examples/src/main/kotlin/com/ably/example/screen/ColorVotingScreen.kt b/examples/src/main/kotlin/com/ably/example/screen/ColorVotingScreen.kt index 6ea1d8c76..1238d7375 100644 --- a/examples/src/main/kotlin/com/ably/example/screen/ColorVotingScreen.kt +++ b/examples/src/main/kotlin/com/ably/example/screen/ColorVotingScreen.kt @@ -16,11 +16,11 @@ import androidx.compose.ui.unit.sp import com.ably.example.getRealtimeChannel import com.ably.example.observeCounter import com.ably.example.observeRootObject -import io.ably.lib.realtime.AblyRealtime +import io.ably.pubsub.realtime.PubSubRealtimeClient @OptIn(ExperimentalMaterial3Api::class) @Composable -fun ColorVotingScreen(realtimeClient: AblyRealtime) { +fun ColorVotingScreen(realtimeClient: PubSubRealtimeClient) { val channel = getRealtimeChannel(realtimeClient, "objects-live-counter") val root = observeRootObject(channel) diff --git a/examples/src/main/kotlin/com/ably/example/screen/MainScreen.kt b/examples/src/main/kotlin/com/ably/example/screen/MainScreen.kt index 48d075e4d..a73a7d3ff 100644 --- a/examples/src/main/kotlin/com/ably/example/screen/MainScreen.kt +++ b/examples/src/main/kotlin/com/ably/example/screen/MainScreen.kt @@ -8,13 +8,13 @@ import androidx.compose.material3.* import androidx.compose.runtime.* import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.vector.ImageVector -import io.ably.lib.realtime.AblyRealtime +import io.ably.pubsub.realtime.PubSubRealtimeClient @OptIn(ExperimentalMaterial3Api::class) @Composable -fun MainScreen(realtimeClient: AblyRealtime) { +fun MainScreen(realtimeClient: PubSubRealtimeClient) { var selectedTab by remember { mutableIntStateOf(0) } - val isSandbox = realtimeClient.options.environment == "sandbox" + val isSandbox = realtimeClient.options.endpoint == "nonprod:sandbox" val tabs = listOf( TabItem("Color Voting", Icons.Default.Favorite), diff --git a/examples/src/main/kotlin/com/ably/example/screen/ObjectsSyncStatus.kt b/examples/src/main/kotlin/com/ably/example/screen/ObjectsSyncStatus.kt index 19060902a..f8e186fb4 100644 --- a/examples/src/main/kotlin/com/ably/example/screen/ObjectsSyncStatus.kt +++ b/examples/src/main/kotlin/com/ably/example/screen/ObjectsSyncStatus.kt @@ -16,9 +16,9 @@ import androidx.compose.ui.platform.testTag import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import com.ably.example.observeObjectsSyncState -import io.ably.lib.liveobjects.path.types.LiveMapPathObject -import io.ably.lib.liveobjects.state.ObjectStateEvent -import io.ably.lib.realtime.Channel +import io.ably.pubsub.liveobjects.path.types.LiveMapPathObject +import io.ably.pubsub.liveobjects.state.ObjectStateEvent +import io.ably.pubsub.realtime.Channel /** * Shows the channel's objects synchronization progress: a spinner with diff --git a/examples/src/main/kotlin/com/ably/example/screen/TaskManagementScreen.kt b/examples/src/main/kotlin/com/ably/example/screen/TaskManagementScreen.kt index a44ffdfd2..f72a9b6c3 100644 --- a/examples/src/main/kotlin/com/ably/example/screen/TaskManagementScreen.kt +++ b/examples/src/main/kotlin/com/ably/example/screen/TaskManagementScreen.kt @@ -18,14 +18,14 @@ import androidx.compose.ui.unit.sp import com.ably.example.getRealtimeChannel import com.ably.example.observeMap import com.ably.example.observeRootObject -import io.ably.lib.liveobjects.value.LiveMapValue -import io.ably.lib.realtime.AblyRealtime +import io.ably.pubsub.liveobjects.value.LiveMapValue +import io.ably.pubsub.realtime.PubSubRealtimeClient import kotlin.uuid.ExperimentalUuidApi import kotlin.uuid.Uuid @OptIn(ExperimentalMaterial3Api::class, ExperimentalUuidApi::class) @Composable -fun TaskManagementScreen(realtimeClient: AblyRealtime) { +fun TaskManagementScreen(realtimeClient: PubSubRealtimeClient) { var taskText by remember { mutableStateOf("") } var editingTaskId by remember { mutableStateOf(null) } var editingText by remember { mutableStateOf("") } diff --git a/gradle.properties b/gradle.properties index 5ade36394..184466b72 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,5 +1,5 @@ -GROUP=io.ably -VERSION_NAME=1.8.2 +GROUP=io.ably.pubsub +VERSION_NAME=2.0.0 POM_INCEPTION_YEAR=2015 POM_URL=https://github.com/ably/ably-pubsub-java POM_SCM_URL=https://github.com/ably/ably-pubsub-java/ diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 177bd0515..9996f4160 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -96,4 +96,5 @@ lombok = { id = "io.freefair.lombok", version.ref = "lombok" } test-retry = { id = "org.gradle.test-retry", version.ref = "test-retry" } android-application = { id = "com.android.application", version.ref = "agp" } kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" } +kotlin-multiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" } kotlin-compose = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" } diff --git a/java/gradle.properties b/java/gradle.properties deleted file mode 100644 index 3bee3c731..000000000 --- a/java/gradle.properties +++ /dev/null @@ -1,8 +0,0 @@ -POM_ARTIFACT_ID=ably-java -POM_NAME=Ably Java client library SDK -POM_DESCRIPTION=A Java Realtime and REST client library SDK for the Ably platform. -POM_PACKAGING=jar - -# The Kotlin plugin is applied for TEST-ONLY Kotlin sources; keep kotlin-stdlib out of :java's -# main scopes so it never enters the published io.ably:ably-java POM/runtime (Java-only artifact). -kotlin.stdlib.default.dependency=false diff --git a/java/src/main/java/io/ably/lib/realtime/Channel.java b/java/src/main/java/io/ably/lib/realtime/Channel.java deleted file mode 100644 index f4100162f..000000000 --- a/java/src/main/java/io/ably/lib/realtime/Channel.java +++ /dev/null @@ -1,14 +0,0 @@ -package io.ably.lib.realtime; - -import io.ably.lib.liveobjects.LiveObjectsPlugin; -import io.ably.lib.types.AblyException; -import io.ably.lib.types.ChannelOptions; -import org.jetbrains.annotations.Nullable; - -public class Channel extends ChannelBase { - Channel(AblyRealtime ably, String name, ChannelOptions options, @Nullable LiveObjectsPlugin liveObjectsPlugin) throws AblyException { - super(ably, name, options, liveObjectsPlugin); - } - - public interface MessageListener extends ChannelBase.MessageListener {} -} diff --git a/java/src/main/java/io/ably/lib/rest/AblyRest.java b/java/src/main/java/io/ably/lib/rest/AblyRest.java deleted file mode 100644 index 7ab6a3390..000000000 --- a/java/src/main/java/io/ably/lib/rest/AblyRest.java +++ /dev/null @@ -1,35 +0,0 @@ -package io.ably.lib.rest; - -import io.ably.lib.types.AblyException; -import io.ably.lib.types.ClientOptions; -import io.ably.lib.util.JavaPlatformAgentProvider; - -/** - * A client that offers a simple stateless API to interact directly with Ably's REST API. - * - * This class implements {@link AutoCloseable} so you can use it in - * try-with-resources constructs and have the JDK close it for you. - */ -public class AblyRest extends AblyBase { - /** - * Constructs a client object using an Ably API key or token string. - *

- * Spec: RSC1 - * @param key The Ably API key or token string used to validate the client. - * @throws AblyException - */ - public AblyRest(String key) throws AblyException { - super(key, new JavaPlatformAgentProvider()); - } - - /** - * Construct a client object using an Ably {@link ClientOptions} object. - *

- * Spec: RSC1 - * @param options A {@link ClientOptions} object to configure the client connection to Ably. - * @throws AblyException - */ - public AblyRest(ClientOptions options) throws AblyException { - super(options, new JavaPlatformAgentProvider()); - } -} diff --git a/java/src/main/java/io/ably/lib/rest/Channel.java b/java/src/main/java/io/ably/lib/rest/Channel.java deleted file mode 100644 index 1c90efb41..000000000 --- a/java/src/main/java/io/ably/lib/rest/Channel.java +++ /dev/null @@ -1,10 +0,0 @@ -package io.ably.lib.rest; - -import io.ably.lib.types.AblyException; -import io.ably.lib.types.ChannelOptions; - -public class Channel extends ChannelBase { - Channel(AblyBase ably, String name, ChannelOptions options) throws AblyException { - super(ably, name, options); - } -} diff --git a/lib/src/main/java/io/ably/lib/liveobjects/adapter/package-info.java b/lib/src/main/java/io/ably/lib/liveobjects/adapter/package-info.java deleted file mode 100644 index 3539eba35..000000000 --- a/lib/src/main/java/io/ably/lib/liveobjects/adapter/package-info.java +++ /dev/null @@ -1,10 +0,0 @@ -/** - * Adapter layer bridging the path-based LiveObjects implementation to the core Ably client. - * {@link io.ably.lib.liveobjects.adapter.AblyClientAdapter} is the abstraction the implementation - * depends on; {@link io.ably.lib.liveobjects.adapter.Adapter} is the default implementation backed - * by an {@link io.ably.lib.realtime.AblyRealtime} client. - * - *

This package is intentionally independent of the legacy {@code io.ably.lib.objects} - * package so the path-based API can evolve on its own. - */ -package io.ably.lib.liveobjects.adapter; diff --git a/lib/src/main/java/io/ably/lib/liveobjects/instance/package-info.java b/lib/src/main/java/io/ably/lib/liveobjects/instance/package-info.java deleted file mode 100644 index df272f592..000000000 --- a/lib/src/main/java/io/ably/lib/liveobjects/instance/package-info.java +++ /dev/null @@ -1,12 +0,0 @@ -/** - * The identity-addressed view of the LiveObjects graph. - * {@link io.ably.lib.liveobjects.instance.Instance} wraps a specific resolved - * LiveObject or primitive value and dereferences it in O(1), following the - * object wherever it sits in the graph. Type-specific operations live on the - * sub-types in {@link io.ably.lib.liveobjects.instance.types}; instance - * subscriptions use {@link io.ably.lib.liveobjects.instance.InstanceListener} and - * {@link io.ably.lib.liveobjects.instance.InstanceSubscriptionEvent}. - * - *

Spec: RTINS1-RTINS16, RTTS7-RTTS9 - */ -package io.ably.lib.liveobjects.instance; diff --git a/lib/src/main/java/io/ably/lib/liveobjects/package-info.java b/lib/src/main/java/io/ably/lib/liveobjects/package-info.java deleted file mode 100644 index 722ac3994..000000000 --- a/lib/src/main/java/io/ably/lib/liveobjects/package-info.java +++ /dev/null @@ -1,17 +0,0 @@ -/** - * The public, strongly-typed LiveObjects API: path-based and instance-based views - * over the objects graph on a channel. - * - *

This root package holds the types shared by both view hierarchies: - * {@link io.ably.lib.liveobjects.ValueType} (the categories a resolved value may have) - * and {@link io.ably.lib.liveobjects.Subscription} (the handle returned by every - * {@code subscribe} operation). The hierarchies themselves live in - * {@link io.ably.lib.liveobjects.path} (lazy, path-addressed references) and - * {@link io.ably.lib.liveobjects.instance} (O(1), identity-addressed references); - * message metadata delivered to subscription listeners lives in - * {@link io.ably.lib.liveobjects.message}, and write-side value types in - * {@link io.ably.lib.liveobjects.value}. - * - *

Spec: RTTS1-RTTS10 (typed-SDK public API partition) - */ -package io.ably.lib.liveobjects; diff --git a/lib/src/main/java/io/ably/lib/liveobjects/path/package-info.java b/lib/src/main/java/io/ably/lib/liveobjects/path/package-info.java deleted file mode 100644 index 00471f2fe..000000000 --- a/lib/src/main/java/io/ably/lib/liveobjects/path/package-info.java +++ /dev/null @@ -1,13 +0,0 @@ -/** - * The path-addressed view of the LiveObjects graph. - * {@link io.ably.lib.liveobjects.path.PathObject} stores a path from the channel's - * root {@code LiveMap} and re-resolves it lazily on every call, so a reference - * survives object replacement at its path. Type-specific operations live on the - * sub-types in {@link io.ably.lib.liveobjects.path.types}; path-based subscriptions - * use {@link io.ably.lib.liveobjects.path.PathObjectListener}, - * {@link io.ably.lib.liveobjects.path.PathObjectSubscriptionEvent} and - * {@link io.ably.lib.liveobjects.path.PathObjectSubscriptionOptions}. - * - *

Spec: RTPO1-RTPO19, RTTS3-RTTS5 - */ -package io.ably.lib.liveobjects.path; diff --git a/lib/src/main/java/io/ably/lib/transport/Defaults.java b/lib/src/main/java/io/ably/lib/transport/Defaults.java deleted file mode 100644 index 66e3e897c..000000000 --- a/lib/src/main/java/io/ably/lib/transport/Defaults.java +++ /dev/null @@ -1,80 +0,0 @@ -package io.ably.lib.transport; - -import io.ably.lib.BuildConfig; -import io.ably.lib.types.ClientOptions; - -public class Defaults { - /** - * The level of compatibility with the Ably service that this SDK supports. - * Also referred to as the 'wire protocol version'. - * This value is presented as a string, as specified in G4a. - *

- * spec: G4 - *

- */ - public static final String ABLY_PROTOCOL_VERSION = "6"; - - public static final String ABLY_AGENT_VERSION = String.format("%s/%s", "ably-java", BuildConfig.VERSION); - - /* realtime params */ - public static final String ABLY_PROTOCOL_VERSION_PARAM = "v"; - public static final String ABLY_AGENT_PARAM = "agent"; - - /* http headers */ - public static final String ABLY_PROTOCOL_VERSION_HEADER = "X-Ably-Version"; - public static final String ABLY_CLIENT_ID_HEADER = "X-Ably-ClientId"; - public static final String ABLY_AGENT_HEADER = "Ably-Agent"; - - /* Hosts */ - public static final String[] HOST_FALLBACKS = { "A.ably-realtime.com", "B.ably-realtime.com", "C.ably-realtime.com", "D.ably-realtime.com", "E.ably-realtime.com" }; - public static final String HOST_REST = "rest.ably.io"; - public static final String HOST_REALTIME = "realtime.ably.io"; - public static final int PORT = 80; - public static final int TLS_PORT = 443; - - /* Timeouts */ - public static int TIMEOUT_CONNECT = 15000; - public static int TIMEOUT_DISCONNECT = 15000; - public static int TIMEOUT_CHANNEL_RETRY = 15000; - - /* TO3l3 */ - public static int TIMEOUT_HTTP_OPEN = 4000; - /* TO3l4 */ - public static int TIMEOUT_HTTP_REQUEST = 10000; - /* TO3l6 */ - public static int httpMaxRetryDuration = 15000; - - /* DF1b */ - public static long realtimeRequestTimeout = 10000L; - /* TO3l2 */ - public static long suspendedRetryTimeout = 30000L; - /* TO3l10 */ - public static long fallbackRetryTimeout = 10*60*1000L; - /* CD2h (but no default in the spec) */ - public static long maxIdleInterval = 20000L; - // 64kB, as per CD2c - public static int maxMessageSize = 65536; - /* DF1a */ - public static long connectionStateTtl = 120000L; - - public static final ITransport.Factory TRANSPORT = new WebSocketTransport.Factory(); - public static final int HTTP_MAX_RETRY_COUNT = 3; - public static final int HTTP_ASYNC_THREADPOOL_SIZE = 64; - - public static int getPort(ClientOptions options) { - return options.tls - ? ((options.tlsPort != 0) ? options.tlsPort : Defaults.TLS_PORT) - : ((options.port != 0) ? options.port : Defaults.PORT); - } - - /* Construct environment fallback hosts as per RSC15i */ - public static String[] getEnvironmentFallbackHosts(String environment) { - return new String[] { - environment + "-a-fallback.ably-realtime.com", - environment + "-b-fallback.ably-realtime.com", - environment + "-c-fallback.ably-realtime.com", - environment + "-d-fallback.ably-realtime.com", - environment + "-e-fallback.ably-realtime.com" - }; - } -} diff --git a/lib/src/main/java/io/ably/lib/transport/Hosts.java b/lib/src/main/java/io/ably/lib/transport/Hosts.java deleted file mode 100644 index 361b983ea..000000000 --- a/lib/src/main/java/io/ably/lib/transport/Hosts.java +++ /dev/null @@ -1,192 +0,0 @@ -package io.ably.lib.transport; - -import io.ably.lib.types.AblyException; -import io.ably.lib.types.ClientOptions; -import io.ably.lib.types.ErrorInfo; -import io.ably.lib.util.Clock; -import io.ably.lib.util.SystemClock; - -import java.util.Arrays; -import java.util.Collections; - - -/** - * Object to encapsulate primary host name and shuffled fallback host names. - * - * Methods on this class are safe to be called from any thread. - */ -public class Hosts { - private final String primaryHost; - private final boolean primaryHostIsDefault; - private final String defaultHost; - private final String[] fallbackHosts; - private final boolean fallbackHostsIsDefault; - private final boolean fallbackHostsUseDefault; - private final long fallbackRetryTimeout; - - private final Preferred preferred = new Preferred(); - private final Clock clock; - - /** - * Create Hosts object - * - * @param primaryHost the primary hostname, null if not configured - * @param defaultHost the default hostname that the primary hostname must - * match for fallback to occur - * @param options ClientOptions to get environment and fallbackHosts from - * - * The fallback and environment processing here is used when the Hosts - * object is used by a ConnectionManager (for a realtime connection) or by - * an HttpCore for a rest connection. The case where the Hosts object is used - * by an HttpCore that is being used by a ConnectionManager goes through this - * code, but the results are ignored because ConnectionManager then calls - * setHost() and fallback is not used. - */ - public Hosts(final String primaryHost, final String defaultHost, final ClientOptions options) throws AblyException { - this.defaultHost = defaultHost; - this.fallbackHostsUseDefault = options.fallbackHostsUseDefault; - boolean hasCustomPrimaryHost = primaryHost != null && !primaryHost.equalsIgnoreCase(defaultHost); - String[] tempFallbackHosts = options.fallbackHosts; - if (options.fallbackHostsUseDefault) { - if (options.fallbackHosts != null) { - throw AblyException.fromErrorInfo(new ErrorInfo("fallbackHosts and fallbackHostsUseDefault cannot both be set", 400, 40000)); - } - if (options.port != 0 || options.tlsPort != 0) { - throw AblyException.fromErrorInfo(new ErrorInfo("fallbackHostsUseDefault cannot be set when port or tlsPort are set", 400, 40000)); - } - tempFallbackHosts = Defaults.HOST_FALLBACKS; - } - - boolean isProduction = options.environment == null || options.environment.isEmpty() || "production".equalsIgnoreCase(options.environment); - - if (!hasCustomPrimaryHost && tempFallbackHosts == null && options.port == 0 && options.tlsPort == 0) { - tempFallbackHosts = isProduction ? Defaults.HOST_FALLBACKS : Defaults.getEnvironmentFallbackHosts(options.environment); - } - - if (hasCustomPrimaryHost) { - this.primaryHost = primaryHost; - if (options.environment != null) { - /* TO3k2: It is never valid to provide both a restHost and environment value - * TO3k3: It is never valid to provide both a realtimeHost and environment value */ - throw AblyException.fromErrorInfo(new ErrorInfo("cannot set both restHost/realtimeHost and environment options", 400, 40000)); - } - } else { - this.primaryHost = isProduction ? defaultHost : options.environment + "-" + defaultHost; - } - primaryHostIsDefault = this.primaryHost.equalsIgnoreCase(defaultHost); - - fallbackHostsIsDefault = Arrays.equals(Defaults.HOST_FALLBACKS, tempFallbackHosts); - fallbackHosts = tempFallbackHosts == null ? new String[] {} : tempFallbackHosts.clone(); - /* RSC15a: shuffle the fallback hosts. */ - Collections.shuffle(Arrays.asList(fallbackHosts)); - fallbackRetryTimeout = options.fallbackRetryTimeout; - this.clock = SystemClock.clockFrom(options); - } - - /** - * set preferred hostname, which might not be the primary - */ - public synchronized void setPreferredHost(final String prefHost, final boolean temporary) { - if (preferred.isHost(prefHost)) { - /* a successful request against a fallback; don't update the expiry time */ - return; - } - if(prefHost.equals(primaryHost)) { - /* a successful request against the primary host; reset */ - preferred.clear(); - } else { - preferred.setHost(prefHost, temporary ? clock.currentTimeMillis() + fallbackRetryTimeout : 0); - } - } - - /** - * Get primary host name - */ - public String getPrimaryHost() { - return primaryHost; - } - - /** - * Get preferred host name (taking into account any affinity to a fallback: see RSC15f) - */ - public synchronized String getPreferredHost() { - final String host = preferred.getHostOrClearIfExpired(clock); - return (host == null) ? primaryHost : host; - } - - /** - * Get next fallback host if any - * - * @param lastHost - * @return Successor host that can be used as a fallback. - * null, if there is no successor fallback available. - */ - public synchronized String getFallback(String lastHost) { - if (fallbackHosts == null) - return null; - int idx; - if (lastHost.equals(primaryHost)) { - /* RSC15b, RTN17b: only use fallback if the hostname has not been overridden - * or if ClientOptions#fallbackHostsUseDefault is true - * or if ClientOptions#fallbackHosts was provided. */ - if (!primaryHostIsDefault && !fallbackHostsUseDefault && fallbackHostsIsDefault) - return null; - idx = 0; - } else if(lastHost.equals(preferred.getHostOrClearIfExpired(clock))) { - /* RSC15f: there was a failure on an unexpired, cached fallback; so try again using the primary */ - preferred.clear(); - return primaryHost; - } else { - /* Onto next fallback. */ - idx = Arrays.asList(fallbackHosts).indexOf(lastHost); - if (idx < 0) { - return null; - } - ++idx; - } - if (idx >= fallbackHosts.length) { - return null; - } - return fallbackHosts[idx]; - } - - public synchronized int fallbackHostsRemaining(String candidateHost) { - if(fallbackHosts == null) { - return 0; - } - if(candidateHost.equals(primaryHost) || candidateHost.equals(preferred.getHost())) { - return fallbackHosts.length; - } - return fallbackHosts.length - Arrays.asList(fallbackHosts).indexOf(candidateHost) - 1; - } - - private static class Preferred { - private String host; - private long expiry; - - public void clear() { - host = null; - expiry = 0; - } - - public boolean isHost(final String host) { - return (this.host == null) ? (host == null) : this.host.equals(host); - } - - public void setHost(final String host, final long expiry) { - this.host = host; - this.expiry = expiry; - } - - public String getHostOrClearIfExpired(Clock clock) { - if(expiry > 0 && expiry <= clock.currentTimeMillis()) { - clear(); // expired, so reset - } - return host; - } - - public String getHost() { - return host; - } - } -} diff --git a/lib/src/main/java/io/ably/annotation/Experimental.java b/lib/src/main/java/io/ably/pubsub/annotation/Experimental.java similarity index 87% rename from lib/src/main/java/io/ably/annotation/Experimental.java rename to lib/src/main/java/io/ably/pubsub/annotation/Experimental.java index 23a7393f4..3504bc7b6 100644 --- a/lib/src/main/java/io/ably/annotation/Experimental.java +++ b/lib/src/main/java/io/ably/pubsub/annotation/Experimental.java @@ -1,4 +1,4 @@ -package io.ably.annotation; +package io.ably.pubsub.annotation; import java.lang.annotation.Documented; diff --git a/lib/src/main/java/io/ably/lib/debug/DebugOptions.java b/lib/src/main/java/io/ably/pubsub/debug/DebugOptions.java similarity index 83% rename from lib/src/main/java/io/ably/lib/debug/DebugOptions.java rename to lib/src/main/java/io/ably/pubsub/debug/DebugOptions.java index 43a212009..32ebf5833 100644 --- a/lib/src/main/java/io/ably/lib/debug/DebugOptions.java +++ b/lib/src/main/java/io/ably/pubsub/debug/DebugOptions.java @@ -1,17 +1,17 @@ -package io.ably.lib.debug; +package io.ably.pubsub.debug; import java.util.List; import java.util.Map; -import io.ably.lib.http.HttpCore; -import io.ably.lib.network.HttpEngine; -import io.ably.lib.network.HttpRequest; -import io.ably.lib.network.WebSocketEngineFactory; -import io.ably.lib.transport.ITransport; -import io.ably.lib.types.AblyException; -import io.ably.lib.types.ClientOptions; -import io.ably.lib.types.ProtocolMessage; -import io.ably.lib.util.Clock; +import io.ably.pubsub.http.HttpCore; +import io.ably.pubsub.network.HttpEngine; +import io.ably.pubsub.network.HttpRequest; +import io.ably.pubsub.network.WebSocketEngineFactory; +import io.ably.pubsub.transport.ITransport; +import io.ably.pubsub.types.AblyException; +import io.ably.pubsub.types.ClientOptions; +import io.ably.pubsub.types.ProtocolMessage; +import io.ably.pubsub.util.Clock; public class DebugOptions extends ClientOptions { public interface RawProtocolListener { @@ -50,8 +50,7 @@ public DebugOptions copy() { copied.logLevel = logLevel; copied.logHandler = logHandler; copied.tls = tls; - copied.restHost = restHost; - copied.realtimeHost = realtimeHost; + copied.endpoint = endpoint; copied.port = port; copied.tlsPort = tlsPort; copied.autoConnect = autoConnect; @@ -60,7 +59,6 @@ public DebugOptions copy() { copied.echoMessages = echoMessages; copied.recover = recover; copied.proxy = proxy; - copied.environment = environment; copied.idempotentRestPublishing = idempotentRestPublishing; copied.httpOpenTimeout = httpOpenTimeout; copied.httpRequestTimeout = httpRequestTimeout; @@ -69,7 +67,6 @@ public DebugOptions copy() { copied.realtimeRequestTimeout = realtimeRequestTimeout; copied.disconnectedRetryTimeout = disconnectedRetryTimeout; copied.suspendedRetryTimeout = suspendedRetryTimeout; - copied.fallbackHostsUseDefault = fallbackHostsUseDefault; copied.fallbackRetryTimeout = fallbackRetryTimeout; copied.defaultTokenParams = defaultTokenParams; copied.channelRetryTimeout = channelRetryTimeout; @@ -87,6 +84,10 @@ public DebugOptions copy() { copied.authParams = authParams; copied.queryTime = queryTime; copied.useTokenAuth = useTokenAuth; + copied.headers = headers; + copied.fallbackHosts = fallbackHosts; + copied.transportParams = transportParams; + copied.agents = agents; return copied; } } diff --git a/lib/src/main/java/io/ably/lib/http/AsyncHttpPaginatedQuery.java b/lib/src/main/java/io/ably/pubsub/http/AsyncHttpPaginatedQuery.java similarity index 92% rename from lib/src/main/java/io/ably/lib/http/AsyncHttpPaginatedQuery.java rename to lib/src/main/java/io/ably/pubsub/http/AsyncHttpPaginatedQuery.java index 3acf5d443..44c701ab0 100644 --- a/lib/src/main/java/io/ably/lib/http/AsyncHttpPaginatedQuery.java +++ b/lib/src/main/java/io/ably/pubsub/http/AsyncHttpPaginatedQuery.java @@ -1,4 +1,4 @@ -package io.ably.lib.http; +package io.ably.pubsub.http; import java.io.UnsupportedEncodingException; import java.net.URLDecoder; @@ -8,15 +8,15 @@ import com.google.gson.JsonElement; -import io.ably.lib.types.AblyException; -import io.ably.lib.types.AsyncHttpPaginatedResponse; -import io.ably.lib.types.Callback; -import io.ably.lib.types.ErrorInfo; -import io.ably.lib.types.Param; +import io.ably.pubsub.types.AblyException; +import io.ably.pubsub.types.AsyncHttpPaginatedResponse; +import io.ably.pubsub.types.Callback; +import io.ably.pubsub.types.ErrorInfo; +import io.ably.pubsub.types.Param; public class AsyncHttpPaginatedQuery implements HttpCore.ResponseHandler { - public AsyncHttpPaginatedQuery(Http http, String method, String path, Param[] headers, Param[] params, + public AsyncHttpPaginatedQuery(HttpRequester http, String method, String path, Param[] headers, Param[] params, HttpCore.RequestBody requestBody) { this.http = http; this.method = method; @@ -33,7 +33,7 @@ public void exec(final AsyncHttpPaginatedResponse.Callback callback) { public void exec(final Param[] params, final AsyncHttpPaginatedResponse.Callback callback) { final HttpCore.ResponseHandler responseHandler = this; - http.request(new Http.Execute() { + http.request(new HttpRequester.Execute() { @Override public void execute(HttpScheduler http, Callback callback) throws AblyException { http.exec(path, method, headers, params, requestBody, responseHandler, true, callback); @@ -154,7 +154,7 @@ public void onError(ErrorInfo reason) { }; } - private final Http http; + private final HttpRequester http; private final String method; private final String path; private final Param[] headers; diff --git a/lib/src/main/java/io/ably/lib/http/AsyncHttpScheduler.java b/lib/src/main/java/io/ably/pubsub/http/AsyncHttpScheduler.java similarity index 93% rename from lib/src/main/java/io/ably/lib/http/AsyncHttpScheduler.java rename to lib/src/main/java/io/ably/pubsub/http/AsyncHttpScheduler.java index 38b45905f..5c966d4c9 100644 --- a/lib/src/main/java/io/ably/lib/http/AsyncHttpScheduler.java +++ b/lib/src/main/java/io/ably/pubsub/http/AsyncHttpScheduler.java @@ -1,12 +1,12 @@ -package io.ably.lib.http; +package io.ably.pubsub.http; -import io.ably.lib.types.ClientOptions; +import io.ably.pubsub.types.ClientOptions; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; -import io.ably.lib.util.Log; +import io.ably.pubsub.util.Log; /** * A HttpScheduler that uses a thread pool to run HTTP operations. @@ -27,7 +27,7 @@ private AsyncHttpScheduler(HttpCore httpCore, CloseableExecutor executor) { /** * [Internal Method] *

- * We use this method to implement proxy Realtime / Rest clients that add additional data to the underlying client. + * We use this method to implement proxy Realtime / HTTP clients that add additional data to the underlying client. */ public AsyncHttpScheduler exchangeHttpCore(HttpCore httpCore) { return new AsyncHttpScheduler(httpCore, this.executor); diff --git a/lib/src/main/java/io/ably/lib/http/AsyncPaginatedQuery.java b/lib/src/main/java/io/ably/pubsub/http/AsyncPaginatedQuery.java similarity index 76% rename from lib/src/main/java/io/ably/lib/http/AsyncPaginatedQuery.java rename to lib/src/main/java/io/ably/pubsub/http/AsyncPaginatedQuery.java index d91a19cf5..a023c4780 100644 --- a/lib/src/main/java/io/ably/lib/http/AsyncPaginatedQuery.java +++ b/lib/src/main/java/io/ably/pubsub/http/AsyncPaginatedQuery.java @@ -1,8 +1,8 @@ -package io.ably.lib.http; +package io.ably.pubsub.http; -import io.ably.lib.types.AsyncPaginatedResult; -import io.ably.lib.types.Callback; -import io.ably.lib.types.Param; +import io.ably.pubsub.types.AsyncPaginatedResult; +import io.ably.pubsub.types.Callback; +import io.ably.pubsub.types.Param; /** * An object that encapsulates parameters of a REST query with a paginated response @@ -21,7 +21,7 @@ public class AsyncPaginatedQuery { * @param params params to pass into the initial query * @param bodyHandler handler to parse response bodies for first and all relative queries */ - public AsyncPaginatedQuery(Http http, String path, Param[] headers, Param[] params, HttpCore.BodyHandler bodyHandler) { + public AsyncPaginatedQuery(HttpRequester http, String path, Param[] headers, Param[] params, HttpCore.BodyHandler bodyHandler) { this(http, path, headers, params, null, bodyHandler); } @@ -34,7 +34,7 @@ public AsyncPaginatedQuery(Http http, String path, Param[] headers, Param[] para * @param params params to pass into the initial query * @param bodyHandler handler to parse response bodies for first and all relative queries */ - public AsyncPaginatedQuery(Http http, String path, Param[] headers, Param[] params, HttpCore.RequestBody requestBody, HttpCore.BodyHandler bodyHandler) { + public AsyncPaginatedQuery(HttpRequester http, String path, Param[] headers, Param[] params, HttpCore.RequestBody requestBody, HttpCore.BodyHandler bodyHandler) { base = new BasePaginatedQuery(http, path, headers, params, requestBody, bodyHandler); } diff --git a/lib/src/main/java/io/ably/lib/rest/Auth.java b/lib/src/main/java/io/ably/pubsub/http/Auth.java similarity index 93% rename from lib/src/main/java/io/ably/lib/rest/Auth.java rename to lib/src/main/java/io/ably/pubsub/http/Auth.java index b6dd2d123..b20bb4d71 100644 --- a/lib/src/main/java/io/ably/lib/rest/Auth.java +++ b/lib/src/main/java/io/ably/pubsub/http/Auth.java @@ -1,4 +1,4 @@ -package io.ably.lib.rest; +package io.ably.pubsub.http; import java.net.URL; import java.nio.charset.Charset; @@ -15,22 +15,22 @@ import com.google.gson.JsonObject; import com.google.gson.JsonParseException; -import io.ably.lib.http.HttpConstants; -import io.ably.lib.http.HttpCore; -import io.ably.lib.http.HttpHelpers; -import io.ably.lib.http.HttpUtils; -import io.ably.lib.types.AblyException; -import io.ably.lib.types.BaseMessage; -import io.ably.lib.types.Capability; -import io.ably.lib.types.ClientOptions; -import io.ably.lib.types.ErrorInfo; -import io.ably.lib.types.NonRetriableTokenException; -import io.ably.lib.types.Param; -import io.ably.lib.util.Base64Coder; -import io.ably.lib.util.Clock; -import io.ably.lib.util.Log; -import io.ably.lib.util.Serialisation; -import io.ably.lib.util.SystemClock; +import io.ably.pubsub.http.HttpConstants; +import io.ably.pubsub.http.HttpCore; +import io.ably.pubsub.http.HttpHelpers; +import io.ably.pubsub.http.HttpUtils; +import io.ably.pubsub.types.AblyException; +import io.ably.pubsub.types.BaseMessage; +import io.ably.pubsub.types.Capability; +import io.ably.pubsub.types.ClientOptions; +import io.ably.pubsub.types.ErrorInfo; +import io.ably.pubsub.types.NonRetriableTokenException; +import io.ably.pubsub.types.Param; +import io.ably.pubsub.util.Base64Coder; +import io.ably.pubsub.util.Clock; +import io.ably.pubsub.util.Log; +import io.ably.pubsub.util.Serialisation; +import io.ably.pubsub.util.SystemClock; /** * Token-generation and authentication operations for the Ably API. @@ -289,24 +289,6 @@ public static class TokenDetails { public TokenDetails() {} public TokenDetails(String token) { this.token = token; } - /** - * A static factory method to create a TokenDetails object from a deserialized - * TokenDetails-like object or a JSON stringified TokenDetails object. - * This method is provided to minimize bugs as a result of differing types by platform for fields such as timestamp or ttl. - * For example, in Ruby ttl in the TokenDetails object is exposed in seconds as that is idiomatic for the language, - * yet when serialized to JSON using to_json it is automatically converted to the Ably standard which is milliseconds. - * By using the fromJson() method when constructing a TokenDetails object, - * Ably ensures that all fields are consistently serialized and deserialized across platforms. - *

- * Spec: TD7 - * @param json A deserialized TokenDetails-like object or a JSON stringified TokenDetails object. - * @return An Ably authentication token. - */ - @Deprecated - public static TokenDetails fromJSON(JsonObject json) { - return Serialisation.gson.fromJson(json, TokenDetails.class); - } - /** * A static factory method to create a TokenDetails object from a deserialized * TokenDetails-like object or a JSON stringified TokenDetails object. @@ -514,25 +496,6 @@ public TokenRequest(TokenParams params) { */ public String mac; - /** - * A static factory method to create a TokenRequest object from a deserialized TokenRequest-like object - * or a JSON stringified TokenRequest object. - * This method is provided to minimize bugs as a result of differing types by platform for fields such as timestamp or ttl. - * For example, in Ruby ttl in the TokenRequest object is exposed in seconds as that is idiomatic for the language, - * yet when serialized to JSON using to_json it is automatically converted to the Ably standard which is milliseconds. - * By using the fromJson() method when constructing a TokenRequest object, - * Ably ensures that all fields are consistently serialized and deserialized across platforms. - *

- * Spec: TE6 - * @param json A deserialized TokenRequest-like object or a JSON stringified TokenRequest object to create a TokenRequest. - * @return An Ably token request object. - * @deprecated use fromJsonElement(JsonObject json) instead - */ - @Deprecated - public static TokenRequest fromJSON(JsonObject json) { - return Serialisation.gson.fromJson(json, TokenRequest.class); - } - /** * A static factory method to create a TokenRequest object from a deserialized TokenRequest-like object * or a JSON stringified TokenRequest object. @@ -607,7 +570,7 @@ public boolean equals(Object obj) { */ public interface AuthUpdateResult{ /** - * Signals an update from {@link io.ably.lib.transport.ConnectionManager#onAuthUpdatedAsync(String, AuthUpdateResult)} + * Signals an update from {@link io.ably.pubsub.transport.ConnectionManager#onAuthUpdatedAsync(String, AuthUpdateResult)} * @param success If Update was successful * @param errorInfo optional errorInfo if update wasn't successful */ @@ -689,7 +652,7 @@ public TokenDetails authorize(TokenParams params, AuthOptions options) throws Ab try { tokenDetails = assertValidToken(params, options, true); } catch (AblyException e) { - /* Give AblyRealtime a chance to update its state and emit an event according to RSA4c */ + /* Give PubSubRealtimeClient a chance to update its state and emit an event according to RSA4c */ ably.onAuthError(e.errorInfo); throw e; } @@ -698,15 +661,6 @@ public TokenDetails authorize(TokenParams params, AuthOptions options) throws Ab return tokenDetails; } - /** - * Alias of authorize() (0.9 RSA10l) - */ - @Deprecated - public TokenDetails authorise(TokenParams params, AuthOptions options) throws AblyException { - Log.w(TAG, "authorise() is deprecated and will be removed in 1.0. Please use authorize() instead"); - return authorize(params, options); - } - /** * Calls the requestToken REST API endpoint to obtain an Ably Token * according to the specified {@link TokenParams} and {@link AuthOptions}. @@ -1004,15 +958,11 @@ public AuthOptions getAuthOptions() { } /** - * Renew auth credentials. - * Will obtain a new token, even if we already have an apparently valid one. - * Authorization will use the parameters supplied on construction. - * @deprecated Because the method returns early before renew() completes and does not provide a completion - * handler for callers. - * Please use {@link Auth#renewAuth} instead + * Obtains a new token even if we already have an apparently valid one, and notifies the + * client that the credentials changed. The internal half of {@link #renewAuth}, for the + * callers that have no completion handler to hand it. */ - @Deprecated - public TokenDetails renew() throws AblyException { + private TokenDetails renewToken() throws AblyException { TokenDetails tokenDetails = assertValidToken(this.tokenParams, this.authOptions, true); ably.onAuthUpdated(tokenDetails.token, false); return tokenDetails; @@ -1050,7 +1000,7 @@ public void onAuthError(ErrorInfo err) { * @param options * @throws AblyException */ - Auth(AblyBase ably, ClientOptions options) throws AblyException { + Auth(PubSubBase ably, ClientOptions options) throws AblyException { this.ably = ably; this.clock = SystemClock.clockFrom(options); this.nanoTimeDelta = clock.currentTimeMillis() - clock.nanoTime()/(1000*1000); @@ -1200,7 +1150,7 @@ public void assertAuthorizationHeader(boolean forceRenew) throws AblyException { authHeader = "Basic " + Base64Coder.encodeString(getBasicCredentials()); } else { if (forceRenew) { - renew(); + renewToken(); } else { assertValidToken(); } @@ -1307,7 +1257,7 @@ public long serverTimestamp() { } private static final String TAG = Auth.class.getName(); - private final AblyBase ably; + private final PubSubBase ably; private final Clock clock; private final AuthMethod method; private AuthOptions authOptions; diff --git a/lib/src/main/java/io/ably/lib/http/BasePaginatedQuery.java b/lib/src/main/java/io/ably/pubsub/http/BasePaginatedQuery.java similarity index 86% rename from lib/src/main/java/io/ably/lib/http/BasePaginatedQuery.java rename to lib/src/main/java/io/ably/pubsub/http/BasePaginatedQuery.java index 38791711e..df6e3d1ec 100644 --- a/lib/src/main/java/io/ably/lib/http/BasePaginatedQuery.java +++ b/lib/src/main/java/io/ably/pubsub/http/BasePaginatedQuery.java @@ -1,4 +1,4 @@ -package io.ably.lib.http; +package io.ably.pubsub.http; import java.io.UnsupportedEncodingException; import java.net.URLDecoder; @@ -8,13 +8,13 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; -import io.ably.lib.types.AblyException; -import io.ably.lib.types.AsyncPaginatedResult; -import io.ably.lib.types.BasePaginatedResult; -import io.ably.lib.types.Callback; -import io.ably.lib.types.ErrorInfo; -import io.ably.lib.types.PaginatedResult; -import io.ably.lib.types.Param; +import io.ably.pubsub.types.AblyException; +import io.ably.pubsub.types.AsyncPaginatedResult; +import io.ably.pubsub.types.BasePaginatedResult; +import io.ably.pubsub.types.Callback; +import io.ably.pubsub.types.ErrorInfo; +import io.ably.pubsub.types.PaginatedResult; +import io.ably.pubsub.types.Param; /** @@ -33,7 +33,7 @@ public class BasePaginatedQuery implements HttpCore.ResponseHandler bodyHandler) { + public BasePaginatedQuery(HttpRequester http, String path, Param[] headers, Param[] params, HttpCore.BodyHandler bodyHandler) { this(http, path, headers, params, null, bodyHandler); } @@ -46,7 +46,7 @@ public BasePaginatedQuery(Http http, String path, Param[] headers, Param[] param * @param params params to pass into the initial query * @param bodyHandler handler to parse response bodies for first and all relative queries */ - public BasePaginatedQuery(Http http, String path, Param[] headers, Param[] params, HttpCore.RequestBody requestBody, HttpCore.BodyHandler bodyHandler) { + public BasePaginatedQuery(HttpRequester http, String path, Param[] headers, Param[] params, HttpCore.RequestBody requestBody, HttpCore.BodyHandler bodyHandler) { this.http = http; this.path = path; this.requestHeaders = headers; @@ -66,12 +66,12 @@ public ResultRequest get() { /** * Get the result of the first query - * @return A Http.Request> giving the first page of results + * @return A HttpRequester.Request> giving the first page of results * together with any available links to related results pages. */ - public Http.Request> exec(final String method) { + public HttpRequester.Request> exec(final String method) { final HttpCore.ResponseHandler> responseHandler = this; - return http.request(new Http.Execute>() { + return http.request(new HttpRequester.Execute>() { @Override public void execute(HttpScheduler http, Callback> callback) throws AblyException { http.exec(path, method, requestHeaders, requestParams, requestBody, responseHandler, true, callback); @@ -100,16 +100,16 @@ private ResultPage(T[] contents, Collection linkHeaders) throws AblyExce public T[] items() { return contents; } @Override - public Http.Request> first() { return getRel(relFirst); } + public HttpRequester.Request> first() { return getRel(relFirst); } @Override - public Http.Request> current() { return getRel(relCurrent); } + public HttpRequester.Request> current() { return getRel(relCurrent); } @Override - public Http.Request> next() { return getRel(relNext); } + public HttpRequester.Request> next() { return getRel(relNext); } - private Http.Request> getRel(final String linkUrl) { - return http.request(new Http.Execute>() { + private HttpRequester.Request> getRel(final String linkUrl) { + return http.request(new HttpRequester.Execute>() { @Override public void execute(HttpScheduler http, Callback> callback) throws AblyException { if(linkUrl == null) { @@ -181,7 +181,7 @@ protected static HashMap parseLinks(Collection linkHeade return result; } - private final Http http; + private final HttpRequester http; private final String path; private final Param[] requestHeaders; private final Param[] requestParams; @@ -189,18 +189,18 @@ protected static HashMap parseLinks(Collection linkHeade private final HttpCore.BodyHandler bodyHandler; /** - * Wraps a Http.Request> to fixate on either a sync or an async interface. + * Wraps a HttpRequester.Request> to fixate on either a sync or an async interface. * - * The Http.Request gives you a BasePaginatedResult whether you call its sync() or its async() + * The HttpRequester.Request gives you a BasePaginatedResult whether you call its sync() or its async() * methods, but we'd like to give it us a PaginatedResult or a AsyncPaginatedResult * respectively, so this does the necessary bridging. * * @param */ public static class ResultRequest { - private final Http.Request> wrappedRequest; + private final HttpRequester.Request> wrappedRequest; - private ResultRequest(Http.Request> wrappedRequest) { + private ResultRequest(HttpRequester.Request> wrappedRequest) { this.wrappedRequest = wrappedRequest; } diff --git a/lib/src/main/java/io/ably/lib/rest/ChannelBase.java b/lib/src/main/java/io/ably/pubsub/http/ChannelBase.java similarity index 85% rename from lib/src/main/java/io/ably/lib/rest/ChannelBase.java rename to lib/src/main/java/io/ably/pubsub/http/ChannelBase.java index ce2aaa573..8440b7530 100644 --- a/lib/src/main/java/io/ably/lib/rest/ChannelBase.java +++ b/lib/src/main/java/io/ably/pubsub/http/ChannelBase.java @@ -1,25 +1,24 @@ -package io.ably.lib.rest; - -import io.ably.lib.http.BasePaginatedQuery; -import io.ably.lib.http.Http; -import io.ably.lib.http.HttpScheduler; -import io.ably.lib.http.HttpCore; -import io.ably.lib.http.HttpUtils; -import io.ably.lib.realtime.CompletionListener; -import io.ably.lib.types.AblyException; -import io.ably.lib.types.AsyncPaginatedResult; -import io.ably.lib.types.Callback; -import io.ably.lib.types.ChannelOptions; -import io.ably.lib.types.Message; -import io.ably.lib.types.MessageOperation; -import io.ably.lib.types.MessageSerializer; -import io.ably.lib.types.PaginatedResult; -import io.ably.lib.types.Param; -import io.ably.lib.types.PresenceMessage; -import io.ably.lib.types.PresenceSerializer; -import io.ably.lib.types.PublishResult; -import io.ably.lib.types.UpdateDeleteResult; -import io.ably.lib.util.Crypto; +package io.ably.pubsub.http; + +import io.ably.pubsub.http.BasePaginatedQuery; +import io.ably.pubsub.http.HttpRequester; +import io.ably.pubsub.http.HttpScheduler; +import io.ably.pubsub.http.HttpCore; +import io.ably.pubsub.http.HttpUtils; +import io.ably.pubsub.types.AblyException; +import io.ably.pubsub.types.AsyncPaginatedResult; +import io.ably.pubsub.types.Callback; +import io.ably.pubsub.types.ChannelOptions; +import io.ably.pubsub.types.Message; +import io.ably.pubsub.types.MessageOperation; +import io.ably.pubsub.types.MessageSerializer; +import io.ably.pubsub.types.PaginatedResult; +import io.ably.pubsub.types.Param; +import io.ably.pubsub.types.PresenceMessage; +import io.ably.pubsub.types.PresenceSerializer; +import io.ably.pubsub.types.PublishResult; +import io.ably.pubsub.types.UpdateDeleteResult; +import io.ably.pubsub.util.Crypto; import org.jetbrains.annotations.Blocking; import org.jetbrains.annotations.NonBlocking; @@ -47,7 +46,7 @@ public class ChannelBase { * Represents the annotations associated with a channel message. * This field provides functionality for managing annotations. */ - public final RestAnnotations annotations; + public final HttpAnnotations annotations; private final MessageEditsMixin messageEditsMixin; @@ -67,7 +66,7 @@ public void publish(String name, Object data) throws AblyException { } @Blocking - void publish(Http http, String name, Object data) throws AblyException { + void publish(HttpRequester http, String name, Object data) throws AblyException { publishImpl(http, name, data).sync(); } @@ -86,32 +85,10 @@ public PublishResult publishWithResult(String name, Object data) throws AblyExce } @Blocking - PublishResult publishWithResult(Http http, String name, Object data) throws AblyException { + PublishResult publishWithResult(HttpRequester http, String name, Object data) throws AblyException { return publishImpl(http, name, data).sync(); } - /** - * Publish a message on this channel using the REST API. - * Since the REST API is stateless, this request is made independently - * of any other request on this or any other channel. - * - * @param name the event name - * @param data the message payload; - * @param listener a listener to be notified of the outcome of this message. - *

- * This listener is invoked on a background thread. - * @deprecated Use {@link #publishAsync(String, Object, Callback)} instead. - */ - @Deprecated - public void publishAsync(String name, Object data, CompletionListener listener) { - publishAsync(ably.http, name, data, listener); - } - - @NonBlocking - void publishAsync(Http http, String name, Object data, CompletionListener listener) { - publishImpl(http, name, data).async(new CompletionListener.ToCallback<>(listener)); - } - /** * Asynchronously publish a message on this channel using the REST API. * Since the REST API is stateless, this request is made independently @@ -129,11 +106,11 @@ public void publishAsync(String name, Object data, Callback callb } @NonBlocking - void publishAsync(Http http, String name, Object data, Callback callback) { + void publishAsync(HttpRequester http, String name, Object data, Callback callback) { publishImpl(http, name, data).async(callback); } - private Http.Request publishImpl(Http http, String name, Object data) { + private HttpRequester.Request publishImpl(HttpRequester http, String name, Object data) { return publishImpl(http, new Message[] {new Message(name, data)}); } @@ -151,7 +128,7 @@ public void publish(final Message[] messages) throws AblyException { } @Blocking - void publish(Http http, final Message[] messages) throws AblyException { + void publish(HttpRequester http, final Message[] messages) throws AblyException { publishImpl(http, messages).sync(); } @@ -168,26 +145,6 @@ public PublishResult publishWithResult(final Message[] messages) throws AblyExce return publishImpl(ably.http, messages).sync(); } - /** - * Asynchronously publish an array of messages on this channel - * - * @param messages the message - * @param listener a listener to be notified of the outcome of this message. - * @deprecated Use {@link #publishAsync(Message[], Callback)} instead. - *

- * This listener is invoked on a background thread. - */ - @Deprecated - @NonBlocking - public void publishAsync(final Message[] messages, final CompletionListener listener) { - publishAsync(ably.http, messages, listener); - } - - @Deprecated - void publishAsync(Http http, final Message[] messages, final CompletionListener listener) { - publishImpl(http, messages).async(new CompletionListener.ToCallback<>(listener)); - } - /** * Asynchronously publish an array of messages on this channel * @@ -201,8 +158,8 @@ public void publishAsync(final Message[] messages, final Callback publishImpl(ably.http, messages).async(callback); } - private Http.Request publishImpl(Http http, final Message[] messages) { - return http.request(new Http.Execute() { + private HttpRequester.Request publishImpl(HttpRequester http, final Message[] messages) { + return http.request(new HttpRequester.Execute() { @Override public void execute(HttpScheduler http, final Callback callback) throws AblyException { /* handle message ids */ @@ -251,7 +208,7 @@ public PaginatedResult history(Param[] params) throws AblyException { return history(ably.http, params); } - PaginatedResult history(Http http, Param[] params) throws AblyException { + PaginatedResult history(HttpRequester http, Param[] params) throws AblyException { return historyImpl(http, params).sync(); } @@ -265,11 +222,11 @@ public void historyAsync(Param[] params, Callback> historyAsync(ably.http, params, callback); } - void historyAsync(Http http, Param[] params, Callback> callback) { + void historyAsync(HttpRequester http, Param[] params, Callback> callback) { historyImpl(http, params).async(callback); } - private BasePaginatedQuery.ResultRequest historyImpl(Http http, Param[] initialParams) { + private BasePaginatedQuery.ResultRequest historyImpl(HttpRequester http, Param[] initialParams) { HttpCore.BodyHandler bodyHandler = MessageSerializer.getMessageResponseHandler(options); final Param[] params = ably.options.addRequestIds ? Param.set(initialParams, Crypto.generateRandomRequestId()) : initialParams; // RSC7c return (new BasePaginatedQuery(http, basePath + "/messages", HttpUtils.defaultAcceptHeaders(ably.options.useBinaryProtocol), params, bodyHandler)).get(); @@ -282,7 +239,7 @@ public class Presence { /** * Retrieves the current members present on the channel and the metadata for each member, - * such as their {@link io.ably.lib.types.PresenceMessage.Action} and ID. Returns a {@link PaginatedResult} object, + * such as their {@link io.ably.pubsub.types.PresenceMessage.Action} and ID. Returns a {@link PaginatedResult} object, * containing an array of {@link PresenceMessage} objects. *

* Spec: RSPa @@ -300,13 +257,13 @@ public PaginatedResult get(Param[] params) throws AblyException return get(ably.http, params); } - PaginatedResult get(Http http, Param[] params) throws AblyException { + PaginatedResult get(HttpRequester http, Param[] params) throws AblyException { return getImpl(http, params).sync(); } /** * Asynchronously retrieves the current members present on the channel and the metadata for each member, - * such as their {@link io.ably.lib.types.PresenceMessage.Action} and ID. Returns a {@link PaginatedResult} object, + * such as their {@link io.ably.pubsub.types.PresenceMessage.Action} and ID. Returns a {@link PaginatedResult} object, * containing an array of {@link PresenceMessage} objects. *

* Spec: RSPa @@ -325,11 +282,11 @@ public void getAsync(Param[] params, Callback> callback) { + void getAsync(HttpRequester http, Param[] params, Callback> callback) { getImpl(http, params).async(callback); } - private BasePaginatedQuery.ResultRequest getImpl(Http http, Param[] initialParams) { + private BasePaginatedQuery.ResultRequest getImpl(HttpRequester http, Param[] initialParams) { HttpCore.BodyHandler bodyHandler = PresenceSerializer.getPresenceResponseHandler(options); final Param[] params = ably.options.addRequestIds ? Param.set(initialParams, Crypto.generateRandomRequestId()) : initialParams; // RSC7c return (new BasePaginatedQuery(http, basePath + "/presence", HttpUtils.defaultAcceptHeaders(ably.options.useBinaryProtocol), params, bodyHandler)).get(); @@ -360,7 +317,7 @@ public PaginatedResult history(Param[] params) throws AblyExcep return history(ably.http, params); } - PaginatedResult history(Http http, Param[] params) throws AblyException { + PaginatedResult history(HttpRequester http, Param[] params) throws AblyException { return historyImpl(http, params).sync(); } @@ -391,11 +348,11 @@ public void historyAsync(Param[] params, Callback> callback) { + void historyAsync(HttpRequester http, Param[] params, Callback> callback) { historyImpl(http, params).async(callback); } - private BasePaginatedQuery.ResultRequest historyImpl(Http http, Param[] initialParams) { + private BasePaginatedQuery.ResultRequest historyImpl(HttpRequester http, Param[] initialParams) { HttpCore.BodyHandler bodyHandler = PresenceSerializer.getPresenceResponseHandler(options); final Param[] params = ably.options.addRequestIds ? Param.set(initialParams, Crypto.generateRandomRequestId()) : initialParams; // RSC7c return (new BasePaginatedQuery(http, basePath + "/presence/history", HttpUtils.defaultAcceptHeaders(ably.options.useBinaryProtocol), params, bodyHandler)).get(); @@ -642,17 +599,17 @@ public void getMessageVersionsAsync(String serial, Param[] params, Callback * Annotations can be retrieved, published, or deleted both synchronously and asynchronously. @@ -32,16 +32,16 @@ * Note: This is an experimental API. While the underlying functionality is stable, * the public API may change in future releases. */ -public class RestAnnotations { +public class HttpAnnotations { - private static final String TAG = RestAnnotations.class.getName(); + private static final String TAG = HttpAnnotations.class.getName(); private final String channelName; - private final Http http; + private final HttpRequester http; private final ClientOptions clientOptions; private final ChannelOptions channelOptions; - public RestAnnotations(String channelName, Http http, ClientOptions clientOptions, ChannelOptions channelOptions) { + public HttpAnnotations(String channelName, HttpRequester http, ClientOptions clientOptions, ChannelOptions channelOptions) { this.channelName = channelName; this.http = http; this.clientOptions = clientOptions; @@ -237,20 +237,20 @@ private String getBasePath(String messageSerial) { return "/channels/" + HttpUtils.encodeURIComponent(channelName) + "/messages/" + HttpUtils.encodeURIComponent(messageSerial) + "/annotations"; } - private Http.Request deleteImpl(String messageSerial, Annotation annotation) throws AblyException { + private HttpRequester.Request deleteImpl(String messageSerial, Annotation annotation) throws AblyException { Log.v(TAG, "delete(): annotation=" + annotation); annotation.action = AnnotationAction.ANNOTATION_DELETE; return sendAnnotationImpl(messageSerial, annotation); } - private Http.Request publishImpl(String messageSerial, Annotation annotation) throws AblyException { + private HttpRequester.Request publishImpl(String messageSerial, Annotation annotation) throws AblyException { Log.v(TAG, "publish(): annotation=" + annotation); // (RSAN1c2) annotation.action = AnnotationAction.ANNOTATION_CREATE; return sendAnnotationImpl(messageSerial, annotation); } - private Http.Request sendAnnotationImpl(String messageSerial, Annotation annotation) throws AblyException { + private HttpRequester.Request sendAnnotationImpl(String messageSerial, Annotation annotation) throws AblyException { // (RSAN1a3) if (annotation.type == null) { throw AblyException.fromErrorInfo(new ErrorInfo("Annotation type must be specified", 400, 40000)); diff --git a/lib/src/main/java/io/ably/lib/http/HttpAuth.java b/lib/src/main/java/io/ably/pubsub/http/HttpAuth.java similarity index 98% rename from lib/src/main/java/io/ably/lib/http/HttpAuth.java rename to lib/src/main/java/io/ably/pubsub/http/HttpAuth.java index 4783f92ca..1d5f30a6b 100644 --- a/lib/src/main/java/io/ably/lib/http/HttpAuth.java +++ b/lib/src/main/java/io/ably/pubsub/http/HttpAuth.java @@ -1,4 +1,4 @@ -package io.ably.lib.http; +package io.ably.pubsub.http; import java.io.UnsupportedEncodingException; import java.security.MessageDigest; @@ -12,9 +12,9 @@ import java.util.Map.Entry; import java.util.Random; -import io.ably.lib.types.AblyException; -import io.ably.lib.types.ErrorInfo; -import io.ably.lib.util.Base64Coder; +import io.ably.pubsub.types.AblyException; +import io.ably.pubsub.types.ErrorInfo; +import io.ably.pubsub.util.Base64Coder; public class HttpAuth { diff --git a/lib/src/main/java/io/ably/pubsub/http/HttpClientFactory.java b/lib/src/main/java/io/ably/pubsub/http/HttpClientFactory.java new file mode 100644 index 000000000..7ab9c3fe5 --- /dev/null +++ b/lib/src/main/java/io/ably/pubsub/http/HttpClientFactory.java @@ -0,0 +1,34 @@ +package io.ably.pubsub.http; + +import io.ably.pubsub.types.AblyException; +import io.ably.pubsub.types.ClientOptions; + +/** + * The seam through which a {@link PubSubHttpClient} is constructed, now that the client's own + * constructors are not public. + *

+ * It exists for the {@code io.ably.pubsub:device} and {@code io.ably.pubsub:server} door + * artifacts, whose builders are the supported way to obtain a client, and for this SDK's own + * tests. It sits in the client's package so that it can reach the non-public constructor, and it + * is compiled into each platform artifact from the shared source directory, so that each one + * constructs its own platform's client. + *

+ * Application code should declare the side it runs on and use that artifact's builder instead: + * {@code io.ably.pubsub.server.PubSubServer#httpClientBuilder()} on infrastructure you control, + * or {@code io.ably.pubsub.device.PubSubDevice#clientBuilder()} on an end-user device. + */ +public final class HttpClientFactory { + private HttpClientFactory() {} + + /** + * Constructs a client from the given options. + * + * @param options the options to configure the client with. + * @return a new client. + * @throws AblyException if the options are invalid, for example if they carry no + * authentication parameters. + */ + public static PubSubHttpClient create(ClientOptions options) throws AblyException { + return new PubSubHttpClient(options); + } +} diff --git a/lib/src/main/java/io/ably/lib/http/HttpConstants.java b/lib/src/main/java/io/ably/pubsub/http/HttpConstants.java similarity index 97% rename from lib/src/main/java/io/ably/lib/http/HttpConstants.java rename to lib/src/main/java/io/ably/pubsub/http/HttpConstants.java index 7e9c04922..80b236b28 100644 --- a/lib/src/main/java/io/ably/lib/http/HttpConstants.java +++ b/lib/src/main/java/io/ably/pubsub/http/HttpConstants.java @@ -1,4 +1,4 @@ -package io.ably.lib.http; +package io.ably.pubsub.http; public class HttpConstants { diff --git a/lib/src/main/java/io/ably/lib/http/HttpCore.java b/lib/src/main/java/io/ably/pubsub/http/HttpCore.java similarity index 95% rename from lib/src/main/java/io/ably/lib/http/HttpCore.java rename to lib/src/main/java/io/ably/pubsub/http/HttpCore.java index 88f2dfb5e..1adf15dc3 100644 --- a/lib/src/main/java/io/ably/lib/http/HttpCore.java +++ b/lib/src/main/java/io/ably/pubsub/http/HttpCore.java @@ -1,28 +1,28 @@ -package io.ably.lib.http; +package io.ably.pubsub.http; import com.google.gson.JsonParseException; -import io.ably.lib.debug.DebugOptions; -import io.ably.lib.network.HttpBody; -import io.ably.lib.network.FailedConnectionException; -import io.ably.lib.network.HttpEngine; -import io.ably.lib.network.HttpEngineConfig; -import io.ably.lib.network.HttpEngineFactory; -import io.ably.lib.network.HttpRequest; -import io.ably.lib.network.HttpResponse; -import io.ably.lib.rest.Auth; -import io.ably.lib.transport.Defaults; -import io.ably.lib.transport.Hosts; -import io.ably.lib.types.AblyException; -import io.ably.lib.types.ClientOptions; -import io.ably.lib.types.ErrorInfo; -import io.ably.lib.types.ErrorResponse; -import io.ably.lib.types.Param; -import io.ably.lib.types.ProxyOptions; -import io.ably.lib.util.AgentHeaderCreator; -import io.ably.lib.util.Base64Coder; -import io.ably.lib.util.ClientOptionsUtils; -import io.ably.lib.util.Log; -import io.ably.lib.util.PlatformAgentProvider; +import io.ably.pubsub.debug.DebugOptions; +import io.ably.pubsub.network.HttpBody; +import io.ably.pubsub.network.FailedConnectionException; +import io.ably.pubsub.network.HttpEngine; +import io.ably.pubsub.network.HttpEngineConfig; +import io.ably.pubsub.network.HttpEngineFactory; +import io.ably.pubsub.network.HttpRequest; +import io.ably.pubsub.network.HttpResponse; +import io.ably.pubsub.http.Auth; +import io.ably.pubsub.transport.Defaults; +import io.ably.pubsub.transport.Hosts; +import io.ably.pubsub.types.AblyException; +import io.ably.pubsub.types.ClientOptions; +import io.ably.pubsub.types.ErrorInfo; +import io.ably.pubsub.types.ErrorResponse; +import io.ably.pubsub.types.Param; +import io.ably.pubsub.types.ProxyOptions; +import io.ably.pubsub.util.AgentHeaderCreator; +import io.ably.pubsub.util.Base64Coder; +import io.ably.pubsub.util.ClientOptionsUtils; +import io.ably.pubsub.util.Log; +import io.ably.pubsub.util.PlatformAgentProvider; import java.io.IOException; import java.lang.reflect.Field; @@ -34,7 +34,7 @@ import java.util.Map; /** - * HttpCore performs authenticated HTTP synchronously. Internal; use Http or HttpScheduler instead. + * HttpCore performs authenticated HTTP synchronously. Internal; use HttpRequester or HttpScheduler instead. */ public class HttpCore { @@ -71,7 +71,7 @@ public class HttpCore { /** * This field is used for analytics purposes. *

- * It holds additional agents that should be added after the Realtime/Rest client is initialized. + * It holds additional agents that should be added after the Realtime/HTTP client is initialized. * - **Static agents** are set in `ClientOptions`. * - **Dynamic agents** are added later by higher-level SDKs like Chat or Asset Tracking * and are provided in the `createWrapperSdkProxy` call. @@ -88,7 +88,7 @@ public HttpCore(ClientOptions options, Auth auth, PlatformAgentProvider platform this.platformAgentProvider = platformAgentProvider; this.scheme = options.tls ? "https://" : "http://"; this.port = Defaults.getPort(options); - this.hosts = new Hosts(options.restHost, Defaults.HOST_REST, options); + this.hosts = new Hosts(options); ProxyOptions proxyOptions = options.proxy; if (proxyOptions != null) { String proxyHost = proxyOptions.host; @@ -495,7 +495,7 @@ private Response executeRequest(HttpRequest request) { /** * [Internal Method] *

- * We use this method to implement proxy Realtime / Rest clients that add additional agents to the underlying client. + * We use this method to implement proxy Realtime / HTTP clients that add additional agents to the underlying client. */ public HttpCore injectDynamicAgents(Map wrapperSDKAgents) { return new HttpCore(this, wrapperSDKAgents); diff --git a/lib/src/main/java/io/ably/lib/http/HttpHelpers.java b/lib/src/main/java/io/ably/pubsub/http/HttpHelpers.java similarity index 81% rename from lib/src/main/java/io/ably/lib/http/HttpHelpers.java rename to lib/src/main/java/io/ably/pubsub/http/HttpHelpers.java index 56862ffd4..c79f5d8e7 100644 --- a/lib/src/main/java/io/ably/lib/http/HttpHelpers.java +++ b/lib/src/main/java/io/ably/pubsub/http/HttpHelpers.java @@ -1,13 +1,13 @@ -package io.ably.lib.http; +package io.ably.pubsub.http; import java.net.URL; -import io.ably.lib.types.AblyException; -import io.ably.lib.types.Callback; -import io.ably.lib.types.ErrorInfo; -import io.ably.lib.types.Param; +import io.ably.pubsub.types.AblyException; +import io.ably.pubsub.types.Callback; +import io.ably.pubsub.types.ErrorInfo; +import io.ably.pubsub.types.Param; -import static io.ably.lib.http.HttpUtils.buildURL; +import static io.ably.pubsub.http.HttpUtils.buildURL; public class HttpHelpers { /** @@ -22,8 +22,8 @@ public class HttpHelpers { * @return * @throws AblyException */ - public static T ablyHttpExecute(Http http, final String path, final String method, final Param[] headers, final Param[] params, final HttpCore.RequestBody requestBody, final HttpCore.ResponseHandler responseHandler, final boolean requireAblyAuth) throws AblyException { - return http.request(new Http.Execute() { + public static T ablyHttpExecute(HttpRequester http, final String path, final String method, final Param[] headers, final Param[] params, final HttpCore.RequestBody requestBody, final HttpCore.ResponseHandler responseHandler, final boolean requireAblyAuth) throws AblyException { + return http.request(new HttpRequester.Execute() { @Override public void execute(HttpScheduler http, Callback callback) throws AblyException { http.exec(path, method, headers, params, requestBody, responseHandler, requireAblyAuth, callback); @@ -111,8 +111,8 @@ public static T httpExecute(HttpCore httpCore, URL url, String method, Param return httpCore.httpExecuteWithRetry(url, method, headers, requestBody, responseHandler, false); } - public static T postSync(final Http http, final String path, final Param[] headers, final Param[] params, final HttpCore.RequestBody requestBody, final HttpCore.ResponseHandler responseHandler, final boolean requireAblyAuth) throws AblyException { - return http.request(new Http.Execute() { + public static T postSync(final HttpRequester http, final String path, final Param[] headers, final Param[] params, final HttpCore.RequestBody requestBody, final HttpCore.ResponseHandler responseHandler, final boolean requireAblyAuth) throws AblyException { + return http.request(new HttpRequester.Execute() { @Override public void execute(HttpScheduler http, Callback callback) throws AblyException { http.post(path, headers, params, requestBody, responseHandler, requireAblyAuth, callback); diff --git a/lib/src/main/java/io/ably/lib/http/HttpPaginatedQuery.java b/lib/src/main/java/io/ably/pubsub/http/HttpPaginatedQuery.java similarity index 92% rename from lib/src/main/java/io/ably/lib/http/HttpPaginatedQuery.java rename to lib/src/main/java/io/ably/pubsub/http/HttpPaginatedQuery.java index f2fe97984..2b88fed26 100644 --- a/lib/src/main/java/io/ably/lib/http/HttpPaginatedQuery.java +++ b/lib/src/main/java/io/ably/pubsub/http/HttpPaginatedQuery.java @@ -1,4 +1,4 @@ -package io.ably.lib.http; +package io.ably.pubsub.http; import java.io.UnsupportedEncodingException; import java.net.URLDecoder; @@ -10,16 +10,16 @@ import com.google.gson.JsonArray; import com.google.gson.JsonElement; -import io.ably.lib.types.AblyException; -import io.ably.lib.types.Callback; -import io.ably.lib.types.ErrorInfo; -import io.ably.lib.types.HttpPaginatedResponse; -import io.ably.lib.types.Param; -import io.ably.lib.util.Serialisation; +import io.ably.pubsub.types.AblyException; +import io.ably.pubsub.types.Callback; +import io.ably.pubsub.types.ErrorInfo; +import io.ably.pubsub.types.HttpPaginatedResponse; +import io.ably.pubsub.types.Param; +import io.ably.pubsub.util.Serialisation; public class HttpPaginatedQuery implements HttpCore.ResponseHandler { - public HttpPaginatedQuery(Http http, String method, String path, Param[] headers, Param[] params, + public HttpPaginatedQuery(HttpRequester http, String method, String path, Param[] headers, Param[] params, HttpCore.RequestBody requestBody) { this.http = http; this.method = method; @@ -48,7 +48,7 @@ public HttpPaginatedResponse exec() throws AblyException { */ public HttpPaginatedResponse exec(final Param[] params) throws AblyException { final HttpCore.ResponseHandler responseHandler = this; - return http.request(new Http.Execute() { + return http.request(new HttpRequester.Execute() { @Override public void execute(HttpScheduler http, Callback callback) throws AblyException { http.exec(path, method, requestHeaders, params, requestBody, responseHandler, true, callback); @@ -154,7 +154,7 @@ public JsonElement[] handleResponseBody(String contentType, byte[] body) throws } }; - private final Http http; + private final HttpRequester http; private final String method; private final String path; private final Param[] requestHeaders; diff --git a/lib/src/main/java/io/ably/lib/http/Http.java b/lib/src/main/java/io/ably/pubsub/http/HttpRequester.java similarity index 77% rename from lib/src/main/java/io/ably/lib/http/Http.java rename to lib/src/main/java/io/ably/pubsub/http/HttpRequester.java index 40ced89e7..eaa6565e2 100644 --- a/lib/src/main/java/io/ably/lib/http/Http.java +++ b/lib/src/main/java/io/ably/pubsub/http/HttpRequester.java @@ -1,17 +1,17 @@ -package io.ably.lib.http; +package io.ably.pubsub.http; -import io.ably.lib.types.AblyException; -import io.ably.lib.types.Callback; -import io.ably.lib.types.ErrorInfo; +import io.ably.pubsub.types.AblyException; +import io.ably.pubsub.types.Callback; +import io.ably.pubsub.types.ErrorInfo; /** * A high level wrapper of both a sync and an async HttpScheduler. */ -public class Http implements AutoCloseable { +public class HttpRequester implements AutoCloseable { private final AsyncHttpScheduler asyncHttp; private final SyncHttpScheduler syncHttp; - public Http(AsyncHttpScheduler asyncHttp, SyncHttpScheduler syncHttp) { + public HttpRequester(AsyncHttpScheduler asyncHttp, SyncHttpScheduler syncHttp) { this.asyncHttp = asyncHttp; this.syncHttp = syncHttp; } @@ -28,10 +28,10 @@ public void connect() { /** * [Internal Method] *

- * We use this method to implement proxy Realtime / Rest clients that add additional data to the underlying client. + * We use this method to implement proxy Realtime / HTTP clients that add additional data to the underlying client. */ - public Http exchangeHttpCore(HttpCore httpCore) { - return new Http(asyncHttp.exchangeHttpCore(httpCore), new SyncHttpScheduler(httpCore)); + public HttpRequester exchangeHttpCore(HttpCore httpCore) { + return new HttpRequester(asyncHttp.exchangeHttpCore(httpCore), new SyncHttpScheduler(httpCore)); } public class Request { @@ -43,7 +43,7 @@ public class Request { public Result sync() throws AblyException { final SyncExecuteResult result = new SyncExecuteResult<>(); - execute.execute(Http.this.syncHttp, new Callback() { + execute.execute(HttpRequester.this.syncHttp, new Callback() { @Override public void onSuccess(Result r) { result.ok = r; @@ -62,7 +62,7 @@ public void onError(ErrorInfo e) { public void async(Callback callback) { try { - execute.execute(Http.this.asyncHttp, callback); + execute.execute(HttpRequester.this.asyncHttp, callback); } catch (AblyException e) { callback.onError(e.errorInfo); } diff --git a/lib/src/main/java/io/ably/lib/http/HttpScheduler.java b/lib/src/main/java/io/ably/pubsub/http/HttpScheduler.java similarity index 97% rename from lib/src/main/java/io/ably/lib/http/HttpScheduler.java rename to lib/src/main/java/io/ably/pubsub/http/HttpScheduler.java index 19aa71afa..c337c375a 100644 --- a/lib/src/main/java/io/ably/lib/http/HttpScheduler.java +++ b/lib/src/main/java/io/ably/pubsub/http/HttpScheduler.java @@ -1,4 +1,4 @@ -package io.ably.lib.http; +package io.ably.pubsub.http; import java.net.URL; import java.util.Locale; @@ -8,19 +8,19 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; -import io.ably.lib.network.HttpCall; -import io.ably.lib.types.AblyException; -import io.ably.lib.types.Callback; -import io.ably.lib.types.ErrorInfo; -import io.ably.lib.types.Param; -import io.ably.lib.util.Clock; -import io.ably.lib.util.Log; -import io.ably.lib.util.SystemClock; +import io.ably.pubsub.network.HttpCall; +import io.ably.pubsub.types.AblyException; +import io.ably.pubsub.types.Callback; +import io.ably.pubsub.types.ErrorInfo; +import io.ably.pubsub.types.Param; +import io.ably.pubsub.util.Clock; +import io.ably.pubsub.util.Log; +import io.ably.pubsub.util.SystemClock; /** * HttpScheduler schedules HttpCore operations to an Executor, exposing a generic async API. * - * Internal; use Http instead. + * Internal; use HttpRequester instead. */ public class HttpScheduler implements AutoCloseable { /** diff --git a/lib/src/main/java/io/ably/lib/http/HttpUtils.java b/lib/src/main/java/io/ably/pubsub/http/HttpUtils.java similarity index 93% rename from lib/src/main/java/io/ably/lib/http/HttpUtils.java rename to lib/src/main/java/io/ably/pubsub/http/HttpUtils.java index fc5fb7894..61e775755 100644 --- a/lib/src/main/java/io/ably/lib/http/HttpUtils.java +++ b/lib/src/main/java/io/ably/pubsub/http/HttpUtils.java @@ -1,4 +1,4 @@ -package io.ably.lib.http; +package io.ably.pubsub.http; import com.google.gson.JsonElement; @@ -16,9 +16,9 @@ import java.util.Map; import java.util.Map.Entry; -import io.ably.lib.types.AblyException; -import io.ably.lib.types.Param; -import io.ably.lib.util.Serialisation; +import io.ably.pubsub.types.AblyException; +import io.ably.pubsub.types.Param; +import io.ably.pubsub.util.Serialisation; /** * HttpUtils: utility methods for Http operations @@ -187,9 +187,20 @@ public static String encodeURIComponent(String str) { return builder.toString(); } + /** + * Formats a host for the authority component of a URL, bracketing an IPv6 literal + * (RFC 3986 section 3.2.2) so that its colons are not mistaken for the port separator. + * + * @param host a hostname, IPv4 address, or IPv6 address, bracketed or not + * @return the host, safe to place between a scheme and a port + */ + public static String hostForUrl(String host) { + return host.indexOf(':') >= 0 && !host.startsWith("[") ? '[' + host + ']' : host; + } + static URL buildURL(String scheme, String host, int port, String path, Param[] params) { StringBuilder builder = new StringBuilder(scheme) - .append(host) + .append(hostForUrl(host)) .append(':') .append(port) .append(HttpUtils.encodeParams(path, params)); diff --git a/lib/src/main/java/io/ably/lib/rest/MessageEditsMixin.java b/lib/src/main/java/io/ably/pubsub/http/MessageEditsMixin.java similarity index 80% rename from lib/src/main/java/io/ably/lib/rest/MessageEditsMixin.java rename to lib/src/main/java/io/ably/pubsub/http/MessageEditsMixin.java index 4ce01f7f5..5b9d419f8 100644 --- a/lib/src/main/java/io/ably/lib/rest/MessageEditsMixin.java +++ b/lib/src/main/java/io/ably/pubsub/http/MessageEditsMixin.java @@ -1,24 +1,24 @@ -package io.ably.lib.rest; +package io.ably.pubsub.http; -import io.ably.lib.http.BasePaginatedQuery; -import io.ably.lib.http.Http; -import io.ably.lib.http.HttpCore; -import io.ably.lib.http.HttpUtils; -import io.ably.lib.types.AblyException; -import io.ably.lib.types.AsyncPaginatedResult; -import io.ably.lib.types.Callback; -import io.ably.lib.types.ChannelOptions; -import io.ably.lib.types.ClientOptions; -import io.ably.lib.types.ErrorInfo; -import io.ably.lib.types.Message; -import io.ably.lib.types.MessageAction; -import io.ably.lib.types.MessageOperation; -import io.ably.lib.types.MessageSerializer; -import io.ably.lib.types.MessageVersion; -import io.ably.lib.types.PaginatedResult; -import io.ably.lib.types.Param; -import io.ably.lib.types.UpdateDeleteResult; -import io.ably.lib.util.Crypto; +import io.ably.pubsub.http.BasePaginatedQuery; +import io.ably.pubsub.http.HttpRequester; +import io.ably.pubsub.http.HttpCore; +import io.ably.pubsub.http.HttpUtils; +import io.ably.pubsub.types.AblyException; +import io.ably.pubsub.types.AsyncPaginatedResult; +import io.ably.pubsub.types.Callback; +import io.ably.pubsub.types.ChannelOptions; +import io.ably.pubsub.types.ClientOptions; +import io.ably.pubsub.types.ErrorInfo; +import io.ably.pubsub.types.Message; +import io.ably.pubsub.types.MessageAction; +import io.ably.pubsub.types.MessageOperation; +import io.ably.pubsub.types.MessageSerializer; +import io.ably.pubsub.types.MessageVersion; +import io.ably.pubsub.types.PaginatedResult; +import io.ably.pubsub.types.Param; +import io.ably.pubsub.types.UpdateDeleteResult; +import io.ably.pubsub.util.Crypto; import org.jetbrains.annotations.Blocking; import org.jetbrains.annotations.NonBlocking; @@ -50,7 +50,7 @@ public MessageEditsMixin(String basePath, ClientOptions clientOptions, ChannelOp * @throws AblyException If the message cannot be retrieved or does not exist. */ @Blocking - public Message getMessage(Http http, String serial) throws AblyException { + public Message getMessage(HttpRequester http, String serial) throws AblyException { return getMessageImpl(http, serial).sync(); } @@ -63,11 +63,11 @@ public Message getMessage(Http http, String serial) throws AblyException { * This callback is invoked on a background thread. */ @NonBlocking - public void getMessageAsync(Http http, String serial, Callback callback) { + public void getMessageAsync(HttpRequester http, String serial, Callback callback) { getMessageImpl(http, serial).async(callback); } - private Http.Request getMessageImpl(Http http, String serial) { + private HttpRequester.Request getMessageImpl(HttpRequester http, String serial) { return http.request((scheduler, callback) -> { if (serial == null || serial.isEmpty()) { throw AblyException.fromErrorInfo(new ErrorInfo("Message serial cannot be empty", 400, 40003)); @@ -101,7 +101,7 @@ private Http.Request getMessageImpl(Http http, String serial) { * @return A {@link UpdateDeleteResult} containing the updated message version serial. */ @Blocking - public UpdateDeleteResult updateMessage(Http http, Message message, MessageOperation operation) throws AblyException { + public UpdateDeleteResult updateMessage(HttpRequester http, Message message, MessageOperation operation) throws AblyException { return updateMessageImpl(http, message, operation, MessageAction.MESSAGE_UPDATE).sync(); } @@ -114,7 +114,7 @@ public UpdateDeleteResult updateMessage(Http http, Message message, MessageOpera * This listener is invoked on a background thread. */ @NonBlocking - public void updateMessageAsync(Http http, Message message, MessageOperation operation, Callback callback) { + public void updateMessageAsync(HttpRequester http, Message message, MessageOperation operation, Callback callback) { updateMessageImpl(http, message, operation, MessageAction.MESSAGE_UPDATE).async(callback); } @@ -131,7 +131,7 @@ public void updateMessageAsync(Http http, Message message, MessageOperation oper * @return A {@link UpdateDeleteResult} containing the deleted message version serial. */ @Blocking - public UpdateDeleteResult deleteMessage(Http http, Message message, MessageOperation operation) throws AblyException { + public UpdateDeleteResult deleteMessage(HttpRequester http, Message message, MessageOperation operation) throws AblyException { return updateMessageImpl(http, message, operation, MessageAction.MESSAGE_DELETE).sync(); } @@ -144,7 +144,7 @@ public UpdateDeleteResult deleteMessage(Http http, Message message, MessageOpera * This listener is invoked on a background thread. */ @NonBlocking - public void deleteMessageAsync(Http http, Message message, MessageOperation operation, Callback callback) { + public void deleteMessageAsync(HttpRequester http, Message message, MessageOperation operation, Callback callback) { updateMessageImpl(http, message, operation, MessageAction.MESSAGE_DELETE).async(callback); } @@ -156,7 +156,7 @@ public void deleteMessageAsync(Http http, Message message, MessageOperation oper * @return A {@link UpdateDeleteResult} containing the updated message version serial. */ @Blocking - public UpdateDeleteResult appendMessage(Http http, Message message, MessageOperation operation) throws AblyException { + public UpdateDeleteResult appendMessage(HttpRequester http, Message message, MessageOperation operation) throws AblyException { return updateMessageImpl(http, message, operation, MessageAction.MESSAGE_APPEND).sync(); } @@ -170,11 +170,11 @@ public UpdateDeleteResult appendMessage(Http http, Message message, MessageOpera * This listener is invoked on a background thread. */ @NonBlocking - public void appendMessageAsync(Http http, Message message, MessageOperation operation, Callback callback) { + public void appendMessageAsync(HttpRequester http, Message message, MessageOperation operation, Callback callback) { updateMessageImpl(http, message, operation, MessageAction.MESSAGE_APPEND).async(callback); } - private Http.Request updateMessageImpl(Http http, Message message, MessageOperation operation, MessageAction action) { + private HttpRequester.Request updateMessageImpl(HttpRequester http, Message message, MessageOperation operation, MessageAction action) { return http.request((scheduler, callback) -> { if (message.serial == null || message.serial.isEmpty()) { throw AblyException.fromErrorInfo(new ErrorInfo("Message serial cannot be empty", 400, 40003)); @@ -228,7 +228,7 @@ private Http.Request updateMessageImpl(Http http, Message me * @throws AblyException If the versions cannot be retrieved. */ @Blocking - public PaginatedResult getMessageVersions(Http http, String serial, Param[] params) throws AblyException { + public PaginatedResult getMessageVersions(HttpRequester http, String serial, Param[] params) throws AblyException { return getMessageVersionsImpl(http, serial, params).sync(); } @@ -240,11 +240,11 @@ public PaginatedResult getMessageVersions(Http http, String serial, Par * @param callback A callback to handle the result asynchronously. */ @NonBlocking - public void getMessageVersionsAsync(Http http, String serial, Param[] params, Callback> callback) throws AblyException { + public void getMessageVersionsAsync(HttpRequester http, String serial, Param[] params, Callback> callback) throws AblyException { getMessageVersionsImpl(http, serial, params).async(callback); } - private BasePaginatedQuery.ResultRequest getMessageVersionsImpl(Http http, String serial, Param[] initialParams) throws AblyException { + private BasePaginatedQuery.ResultRequest getMessageVersionsImpl(HttpRequester http, String serial, Param[] initialParams) throws AblyException { if (serial == null || serial.isEmpty()) { throw AblyException.fromErrorInfo(new ErrorInfo("Message serial cannot be empty", 400, 40003)); } diff --git a/lib/src/main/java/io/ably/lib/http/PaginatedQuery.java b/lib/src/main/java/io/ably/pubsub/http/PaginatedQuery.java similarity index 76% rename from lib/src/main/java/io/ably/lib/http/PaginatedQuery.java rename to lib/src/main/java/io/ably/pubsub/http/PaginatedQuery.java index cf8ee8722..bb8560276 100644 --- a/lib/src/main/java/io/ably/lib/http/PaginatedQuery.java +++ b/lib/src/main/java/io/ably/pubsub/http/PaginatedQuery.java @@ -1,8 +1,8 @@ -package io.ably.lib.http; +package io.ably.pubsub.http; -import io.ably.lib.types.AblyException; -import io.ably.lib.types.PaginatedResult; -import io.ably.lib.types.Param; +import io.ably.pubsub.types.AblyException; +import io.ably.pubsub.types.PaginatedResult; +import io.ably.pubsub.types.Param; /** * An object that encapsulates parameters of a REST query with a paginated response @@ -21,7 +21,7 @@ public class PaginatedQuery { * @param params params to pass into the initial query * @param bodyHandler handler to parse response bodies for first and all relative queries */ - public PaginatedQuery(Http http, String path, Param[] headers, Param[] params, HttpCore.BodyHandler bodyHandler) { + public PaginatedQuery(HttpRequester http, String path, Param[] headers, Param[] params, HttpCore.BodyHandler bodyHandler) { this(http, path, headers, params, null, bodyHandler); } @@ -34,7 +34,7 @@ public PaginatedQuery(Http http, String path, Param[] headers, Param[] params, H * @param params params to pass into the initial query * @param bodyHandler handler to parse response bodies for first and all relative queries */ - public PaginatedQuery(Http http, String path, Param[] headers, Param[] params, HttpCore.RequestBody requestBody, HttpCore.BodyHandler bodyHandler) { + public PaginatedQuery(HttpRequester http, String path, Param[] headers, Param[] params, HttpCore.RequestBody requestBody, HttpCore.BodyHandler bodyHandler) { base = new BasePaginatedQuery(http, path, headers, params, requestBody, bodyHandler); } diff --git a/lib/src/main/java/io/ably/lib/rest/AblyBase.java b/lib/src/main/java/io/ably/pubsub/http/PubSubBase.java similarity index 86% rename from lib/src/main/java/io/ably/lib/rest/AblyBase.java rename to lib/src/main/java/io/ably/pubsub/http/PubSubBase.java index 67f1d800b..c9987db89 100644 --- a/lib/src/main/java/io/ably/lib/rest/AblyBase.java +++ b/lib/src/main/java/io/ably/pubsub/http/PubSubBase.java @@ -1,41 +1,31 @@ -package io.ably.lib.rest; - -import io.ably.annotation.Experimental; -import io.ably.lib.http.AsyncHttpScheduler; -import io.ably.lib.http.Http; -import io.ably.lib.http.HttpCore; -import io.ably.lib.http.HttpScheduler; -import io.ably.lib.http.SyncHttpScheduler; -import io.ably.lib.http.AsyncHttpPaginatedQuery; -import io.ably.lib.http.AsyncPaginatedQuery; -import io.ably.lib.http.HttpPaginatedQuery; -import io.ably.lib.http.HttpUtils; -import io.ably.lib.http.PaginatedQuery; -import io.ably.lib.platform.Platform; -import io.ably.lib.push.Push; -import io.ably.lib.realtime.Connection; -import io.ably.lib.transport.Defaults; -import io.ably.lib.types.AblyException; -import io.ably.lib.types.AsyncHttpPaginatedResponse; -import io.ably.lib.types.AsyncPaginatedResult; -import io.ably.lib.types.Callback; -import io.ably.lib.types.ChannelOptions; -import io.ably.lib.types.ClientOptions; -import io.ably.lib.types.ErrorInfo; -import io.ably.lib.types.HttpPaginatedResponse; -import io.ably.lib.types.Message; -import io.ably.lib.types.MessageSerializer; -import io.ably.lib.types.PaginatedResult; -import io.ably.lib.types.Param; -import io.ably.lib.types.PublishResponse; -import io.ably.lib.types.ReadOnlyMap; -import io.ably.lib.types.Stats; -import io.ably.lib.types.StatsReader; -import io.ably.lib.util.Crypto; -import io.ably.lib.util.InternalMap; -import io.ably.lib.util.Log; -import io.ably.lib.util.PlatformAgentProvider; -import io.ably.lib.util.Serialisation; +package io.ably.pubsub.http; + +import io.ably.pubsub.annotation.Experimental; +import io.ably.pubsub.platform.Platform; +import io.ably.pubsub.push.Push; +import io.ably.pubsub.realtime.Connection; +import io.ably.pubsub.transport.Defaults; +import io.ably.pubsub.types.AblyException; +import io.ably.pubsub.types.AsyncHttpPaginatedResponse; +import io.ably.pubsub.types.AsyncPaginatedResult; +import io.ably.pubsub.types.Callback; +import io.ably.pubsub.types.ChannelOptions; +import io.ably.pubsub.types.ClientOptions; +import io.ably.pubsub.types.ErrorInfo; +import io.ably.pubsub.types.HttpPaginatedResponse; +import io.ably.pubsub.types.Message; +import io.ably.pubsub.types.MessageSerializer; +import io.ably.pubsub.types.PaginatedResult; +import io.ably.pubsub.types.Param; +import io.ably.pubsub.types.PublishResponse; +import io.ably.pubsub.types.ReadOnlyMap; +import io.ably.pubsub.types.Stats; +import io.ably.pubsub.types.StatsReader; +import io.ably.pubsub.util.Crypto; +import io.ably.pubsub.util.InternalMap; +import io.ably.pubsub.util.Log; +import io.ably.pubsub.util.PlatformAgentProvider; +import io.ably.pubsub.util.Serialisation; /** * A client that offers a simple stateless API to interact directly with Ably's REST API. @@ -43,7 +33,7 @@ * This class implements {@link AutoCloseable} so you can use it in * try-with-resources constructs and have the JDK close it for you. */ -public abstract class AblyBase implements AutoCloseable { +public abstract class PubSubBase implements AutoCloseable { /** * Some REST endpoints (e.g., stats and batch) changed in protocol v3. @@ -56,7 +46,7 @@ public abstract class AblyBase implements AutoCloseable { private static final int LEGACY_API_PROTOCOL_V2 = 2; public final ClientOptions options; - public final Http http; + public final HttpRequester http; public final HttpCore httpCore; /** @@ -88,7 +78,7 @@ public abstract class AblyBase implements AutoCloseable { * @param platformAgentProvider provides platform agent for the agent header. * @throws AblyException */ - public AblyBase(String key, PlatformAgentProvider platformAgentProvider) throws AblyException { + public PubSubBase(String key, PlatformAgentProvider platformAgentProvider) throws AblyException { this(new ClientOptions(key), platformAgentProvider); } @@ -100,7 +90,7 @@ public AblyBase(String key, PlatformAgentProvider platformAgentProvider) throws * @param platformAgentProvider provides platform agent for the agent header. * @throws AblyException */ - public AblyBase(ClientOptions options, PlatformAgentProvider platformAgentProvider) throws AblyException { + public PubSubBase(ClientOptions options, PlatformAgentProvider platformAgentProvider) throws AblyException { /* normalise options */ if(options == null) { String msg = "no options provided"; @@ -117,7 +107,7 @@ public AblyBase(ClientOptions options, PlatformAgentProvider platformAgentProvid this.platformAgentProvider = platformAgentProvider; auth = new Auth(this, options); httpCore = new HttpCore(options, auth, this.platformAgentProvider); - http = new Http(new AsyncHttpScheduler(httpCore, options), new SyncHttpScheduler(httpCore)); + http = new HttpRequester(new AsyncHttpScheduler(httpCore, options), new SyncHttpScheduler(httpCore)); channels = new InternalChannels(); @@ -126,7 +116,7 @@ public AblyBase(ClientOptions options, PlatformAgentProvider platformAgentProvid } /** - * Causes the connection to close, entering the [{@link io.ably.lib.realtime.ConnectionState#closing} state. + * Causes the connection to close, entering the [{@link io.ably.pubsub.realtime.ConnectionState#closing} state. * Once closed, the library does not attempt to re-establish the connection without an explicit call to * {@link Connection#connect()}. *

@@ -139,7 +129,7 @@ public void close() throws Exception { } /** - * Internal method, used for `RealtimeClient` only + * Internal method, used for `PubSubRealtimeClient` only */ protected void connect() { http.connect(); @@ -173,7 +163,7 @@ public Channel get(String channelName, ChannelOptions channelOptions) throws Abl return channel; } - channel = new Channel(AblyBase.this, channelName, channelOptions); + channel = new Channel(PubSubBase.this, channelName, channelOptions); map.put(channelName, channel); return channel; } @@ -200,7 +190,7 @@ public long time() throws AblyException { return time(http); } - long time(Http http) throws AblyException { + long time(HttpRequester http) throws AblyException { return timeImpl(http).sync(); } @@ -221,13 +211,13 @@ public void timeAsync(Callback callback) { timeAsync(http, callback); } - void timeAsync(Http http, Callback callback) { + void timeAsync(HttpRequester http, Callback callback) { timeImpl(http).async(callback); } - private Http.Request timeImpl(Http http) { + private HttpRequester.Request timeImpl(HttpRequester http) { final Param[] params = this.options.addRequestIds ? Param.array(Crypto.generateRandomRequestId()) : null; // RSC7c - return http.request(new Http.Execute() { + return http.request(new HttpRequester.Execute() { @Override public void execute(HttpScheduler http, Callback callback) throws AblyException { http.get("/time", HttpUtils.defaultAcceptHeaders(false), params, new HttpCore.ResponseHandler() { @@ -266,7 +256,7 @@ public PaginatedResult stats(Param[] params) throws AblyException { return stats(http, params); } - PaginatedResult stats(Http http, Param[] params) throws AblyException { + PaginatedResult stats(HttpRequester http, Param[] params) throws AblyException { return new PaginatedQuery<>( http, "/stats", @@ -304,7 +294,7 @@ public void statsAsync(Param[] params, Callback> cal statsAsync(http, params, callback); } - void statsAsync(Http http, Param[] params, Callback> callback) { + void statsAsync(HttpRequester http, Param[] params, Callback> callback) { (new AsyncPaginatedQuery( http, "/stats", @@ -341,7 +331,7 @@ public HttpPaginatedResponse request(String method, String path, Param[] params, return request(http, method, path, params, body, headers); } - HttpPaginatedResponse request(Http http, String method, String path, Param[] params, HttpCore.RequestBody body, Param[] headers) throws AblyException { + HttpPaginatedResponse request(HttpRequester http, String method, String path, Param[] params, HttpCore.RequestBody body, Param[] headers) throws AblyException { headers = HttpUtils.mergeHeaders(HttpUtils.defaultAcceptHeaders(false), headers); return new HttpPaginatedQuery(http, method, path, headers, params, body).exec(); } @@ -372,7 +362,7 @@ public void requestAsync(String method, String path, Param[] params, HttpCore.Re requestAsync(http, method, path, params, body, headers, callback); } - void requestAsync(Http http, String method, String path, Param[] params, HttpCore.RequestBody body, Param[] headers, final AsyncHttpPaginatedResponse.Callback callback) { + void requestAsync(HttpRequester http, String method, String path, Param[] params, HttpCore.RequestBody body, Param[] headers, final AsyncHttpPaginatedResponse.Callback callback) { headers = HttpUtils.mergeHeaders(HttpUtils.defaultAcceptHeaders(false), headers); (new AsyncHttpPaginatedQuery(http, method, path, headers, params, body)).exec(callback); } @@ -447,7 +437,7 @@ public void publishBatchAsync(Message.Batch[] pubSpecs, ChannelOptions channelOp publishBatchImpl(pubSpecs, channelOptions, params).async(callback); } - private Http.Request publishBatchImpl(final Message.Batch[] pubSpecs, ChannelOptions channelOptions, final Param[] initialParams) throws AblyException { + private HttpRequester.Request publishBatchImpl(final Message.Batch[] pubSpecs, ChannelOptions channelOptions, final Param[] initialParams) throws AblyException { boolean hasClientSuppliedId = false; for(Message.Batch spec : pubSpecs) { for(Message message : spec.messages) { @@ -466,7 +456,7 @@ private Http.Request publishBatchImpl(final Message.Batch[] p } } } - return http.request(new Http.Execute() { + return http.request(new HttpRequester.Execute() { @Override public void execute(HttpScheduler http, final Callback callback) throws AblyException { HttpCore.RequestBody requestBody = options.useBinaryProtocol ? MessageSerializer.asMsgpackRequest(pubSpecs) : MessageSerializer.asJSONRequest(pubSpecs); @@ -490,7 +480,7 @@ public PublishResponse[] handleResponse(HttpCore.Response response, ErrorInfo er } /** - * Override this method in AblyRealtime and pass updated token to ConnectionManager + * Override this method in PubSubRealtimeClient and pass updated token to ConnectionManager * @param token new token * @param waitForResponse wait for server response before returning from method * @throws AblyException @@ -500,7 +490,7 @@ protected void onAuthUpdated(String token, boolean waitForResponse) throws AblyE } /** - * Override this method in AblyRealtime and pass updated token to ConnectionManager + * Override this method in PubSubRealtimeClient and pass updated token to ConnectionManager * @param token new token * @param authUpdateResult Callback result */ diff --git a/lib/src/main/java/io/ably/lib/http/SyncHttpScheduler.java b/lib/src/main/java/io/ably/pubsub/http/SyncHttpScheduler.java similarity index 75% rename from lib/src/main/java/io/ably/lib/http/SyncHttpScheduler.java rename to lib/src/main/java/io/ably/pubsub/http/SyncHttpScheduler.java index 052119586..f99aab50b 100644 --- a/lib/src/main/java/io/ably/lib/http/SyncHttpScheduler.java +++ b/lib/src/main/java/io/ably/pubsub/http/SyncHttpScheduler.java @@ -1,6 +1,6 @@ -package io.ably.lib.http; +package io.ably.pubsub.http; -import io.ably.lib.util.CurrentThreadExecutor; +import io.ably.pubsub.util.CurrentThreadExecutor; /** * A HttpScheduler that runs everything in the current thread. diff --git a/lib/src/main/java/io/ably/lib/liveobjects/LiveObjectsPlugin.java b/lib/src/main/java/io/ably/pubsub/liveobjects/LiveObjectsPlugin.java similarity index 82% rename from lib/src/main/java/io/ably/lib/liveobjects/LiveObjectsPlugin.java rename to lib/src/main/java/io/ably/pubsub/liveobjects/LiveObjectsPlugin.java index 41ab0622c..c1af27ee1 100644 --- a/lib/src/main/java/io/ably/lib/liveobjects/LiveObjectsPlugin.java +++ b/lib/src/main/java/io/ably/pubsub/liveobjects/LiveObjectsPlugin.java @@ -1,11 +1,11 @@ -package io.ably.lib.liveobjects; +package io.ably.pubsub.liveobjects; -import io.ably.lib.liveobjects.adapter.AblyClientAdapter; -import io.ably.lib.liveobjects.adapter.Adapter; -import io.ably.lib.realtime.AblyRealtime; -import io.ably.lib.realtime.ChannelState; -import io.ably.lib.types.ProtocolMessage; -import io.ably.lib.util.Log; +import io.ably.pubsub.liveobjects.adapter.AblyClientAdapter; +import io.ably.pubsub.liveobjects.adapter.Adapter; +import io.ably.pubsub.realtime.PubSubRealtimeClient; +import io.ably.pubsub.realtime.ChannelState; +import io.ably.pubsub.types.ProtocolMessage; +import io.ably.pubsub.util.Log; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -70,31 +70,31 @@ public interface LiveObjectsPlugin { * from the classpath. Returns a new plugin instance on every successful invocation, or * {@code null} if the LiveObjects plugin is not present in the classpath. * - * @param ablyRealtime the AblyRealtime client used to build the adapter the plugin runs against. + * @param realtimeClient the PubSubRealtimeClient client used to build the adapter the plugin runs against. * @return a new {@link LiveObjectsPlugin} instance, or {@code null} if the plugin is unavailable. */ @Nullable - static LiveObjectsPlugin tryInitialize(@NotNull AblyRealtime ablyRealtime) { - return Factory.create(ablyRealtime); + static LiveObjectsPlugin tryInitialize(@NotNull PubSubRealtimeClient realtimeClient) { + return Factory.create(realtimeClient); } /** * Reflectively constructs the LiveObjects plugin implementation. Lives in a nested class so the * implementation-class name stays {@code private} (interface fields are forced {@code public}), - * mirroring {@link io.ably.lib.liveobjects.serialization.ObjectSerializer.Holder}. Unlike {@code Holder} + * mirroring {@link io.ably.pubsub.liveobjects.serialization.ObjectSerializer.Holder}. Unlike {@code Holder} * this is stateless: {@link #create} returns a new instance on every call. */ final class Factory { private static final String TAG = LiveObjectsPlugin.Factory.class.getName(); - private static final String IMPLEMENTATION_CLASS = "io.ably.lib.liveobjects.DefaultLiveObjectsPlugin"; + private static final String IMPLEMENTATION_CLASS = "io.ably.pubsub.liveobjects.DefaultLiveObjectsPlugin"; private Factory() {} @Nullable - static LiveObjectsPlugin create(@NotNull AblyRealtime ablyRealtime) { + static LiveObjectsPlugin create(@NotNull PubSubRealtimeClient realtimeClient) { try { Class objectsImplementation = Class.forName(IMPLEMENTATION_CLASS); - AblyClientAdapter adapter = new Adapter(ablyRealtime); + AblyClientAdapter adapter = new Adapter(realtimeClient); return (LiveObjectsPlugin) objectsImplementation .getDeclaredConstructor(AblyClientAdapter.class) .newInstance(adapter); diff --git a/lib/src/main/java/io/ably/lib/liveobjects/RealtimeObject.java b/lib/src/main/java/io/ably/pubsub/liveobjects/RealtimeObject.java similarity index 92% rename from lib/src/main/java/io/ably/lib/liveobjects/RealtimeObject.java rename to lib/src/main/java/io/ably/pubsub/liveobjects/RealtimeObject.java index e9dc90a7d..cb13ef4ee 100644 --- a/lib/src/main/java/io/ably/lib/liveobjects/RealtimeObject.java +++ b/lib/src/main/java/io/ably/pubsub/liveobjects/RealtimeObject.java @@ -1,10 +1,10 @@ -package io.ably.lib.liveobjects; +package io.ably.pubsub.liveobjects; -import io.ably.lib.liveobjects.path.types.LiveMapPathObject; -import io.ably.lib.liveobjects.state.ObjectStateChange; -import io.ably.lib.liveobjects.state.ObjectStateEvent; -import io.ably.lib.types.AblyException; -import io.ably.lib.types.ErrorInfo; +import io.ably.pubsub.liveobjects.path.types.LiveMapPathObject; +import io.ably.pubsub.liveobjects.state.ObjectStateChange; +import io.ably.pubsub.liveobjects.state.ObjectStateEvent; +import io.ably.pubsub.types.AblyException; +import io.ably.pubsub.types.ErrorInfo; import org.jetbrains.annotations.NotNull; import java.util.concurrent.CompletableFuture; diff --git a/lib/src/main/java/io/ably/lib/liveobjects/Subscription.java b/lib/src/main/java/io/ably/pubsub/liveobjects/Subscription.java similarity index 95% rename from lib/src/main/java/io/ably/lib/liveobjects/Subscription.java rename to lib/src/main/java/io/ably/pubsub/liveobjects/Subscription.java index 720bf9a79..116b277a9 100644 --- a/lib/src/main/java/io/ably/lib/liveobjects/Subscription.java +++ b/lib/src/main/java/io/ably/pubsub/liveobjects/Subscription.java @@ -1,4 +1,4 @@ -package io.ably.lib.liveobjects; +package io.ably.pubsub.liveobjects; /** * Represents a registration for receiving events from a subscribe operation. diff --git a/lib/src/main/java/io/ably/lib/liveobjects/ValueType.java b/lib/src/main/java/io/ably/pubsub/liveobjects/ValueType.java similarity index 96% rename from lib/src/main/java/io/ably/lib/liveobjects/ValueType.java rename to lib/src/main/java/io/ably/pubsub/liveobjects/ValueType.java index ac050adf1..a1985145a 100644 --- a/lib/src/main/java/io/ably/lib/liveobjects/ValueType.java +++ b/lib/src/main/java/io/ably/pubsub/liveobjects/ValueType.java @@ -1,4 +1,4 @@ -package io.ably.lib.liveobjects; +package io.ably.pubsub.liveobjects; /** * The type of a value resolved by a {@code PathObject} or wrapped by an diff --git a/lib/src/main/java/io/ably/lib/liveobjects/adapter/AblyClientAdapter.java b/lib/src/main/java/io/ably/pubsub/liveobjects/adapter/AblyClientAdapter.java similarity index 77% rename from lib/src/main/java/io/ably/lib/liveobjects/adapter/AblyClientAdapter.java rename to lib/src/main/java/io/ably/pubsub/liveobjects/adapter/AblyClientAdapter.java index 6a63a8783..dc7208857 100644 --- a/lib/src/main/java/io/ably/lib/liveobjects/adapter/AblyClientAdapter.java +++ b/lib/src/main/java/io/ably/pubsub/liveobjects/adapter/AblyClientAdapter.java @@ -1,19 +1,19 @@ -package io.ably.lib.liveobjects.adapter; +package io.ably.pubsub.liveobjects.adapter; -import io.ably.lib.realtime.ChannelBase; -import io.ably.lib.realtime.Connection; -import io.ably.lib.types.AblyException; -import io.ably.lib.types.ClientOptions; +import io.ably.pubsub.realtime.ChannelBase; +import io.ably.pubsub.realtime.Connection; +import io.ably.pubsub.types.AblyException; +import io.ably.pubsub.types.ClientOptions; import org.jetbrains.annotations.Blocking; import org.jetbrains.annotations.NotNull; /** * Bridges the path-based LiveObjects implementation to the core Ably client, exposing the * client configuration, connection and channel state it needs without coupling it to the - * concrete {@link io.ably.lib.realtime.AblyRealtime} type. + * concrete {@link io.ably.pubsub.realtime.PubSubRealtimeClient} type. * - *

This is the adapter for the path-based {@code io.ably.lib.object} API and is intentionally - * kept independent of the legacy {@code io.ably.lib.objects} package. + *

This is the adapter for the path-based {@code io.ably.pubsub.object} API and is intentionally + * kept independent of the legacy {@code io.ably.pubsub.objects} package. */ public interface AblyClientAdapter { /** diff --git a/lib/src/main/java/io/ably/lib/liveobjects/adapter/Adapter.java b/lib/src/main/java/io/ably/pubsub/liveobjects/adapter/Adapter.java similarity index 68% rename from lib/src/main/java/io/ably/lib/liveobjects/adapter/Adapter.java rename to lib/src/main/java/io/ably/pubsub/liveobjects/adapter/Adapter.java index a935f68bc..c08d1ed05 100644 --- a/lib/src/main/java/io/ably/lib/liveobjects/adapter/Adapter.java +++ b/lib/src/main/java/io/ably/pubsub/liveobjects/adapter/Adapter.java @@ -1,26 +1,26 @@ -package io.ably.lib.liveobjects.adapter; +package io.ably.pubsub.liveobjects.adapter; -import io.ably.lib.realtime.AblyRealtime; -import io.ably.lib.realtime.Channel; -import io.ably.lib.realtime.ChannelBase; -import io.ably.lib.realtime.Connection; -import io.ably.lib.types.AblyException; -import io.ably.lib.types.ClientOptions; -import io.ably.lib.types.ErrorInfo; -import io.ably.lib.types.ReadOnlyMap; -import io.ably.lib.util.Log; +import io.ably.pubsub.realtime.PubSubRealtimeClient; +import io.ably.pubsub.realtime.Channel; +import io.ably.pubsub.realtime.ChannelBase; +import io.ably.pubsub.realtime.Connection; +import io.ably.pubsub.types.AblyException; +import io.ably.pubsub.types.ClientOptions; +import io.ably.pubsub.types.ErrorInfo; +import io.ably.pubsub.types.ReadOnlyMap; +import io.ably.pubsub.util.Log; import org.jetbrains.annotations.NotNull; /** - * Default {@link AblyClientAdapter} implementation backed by an {@link AblyRealtime} client. - * Holding the {@code AblyRealtime} reference gives the path-based LiveObjects implementation + * Default {@link AblyClientAdapter} implementation backed by an {@link PubSubRealtimeClient} client. + * Holding the {@code PubSubRealtimeClient} reference gives the path-based LiveObjects implementation * access to the full client configuration and runtime state it may need. */ public class Adapter implements AblyClientAdapter { - private final AblyRealtime ably; + private final PubSubRealtimeClient ably; private static final String TAG = AblyClientAdapter.class.getName(); - public Adapter(@NotNull AblyRealtime ably) { + public Adapter(@NotNull PubSubRealtimeClient ably) { this.ably = ably; } diff --git a/lib/src/main/java/io/ably/pubsub/liveobjects/adapter/package-info.java b/lib/src/main/java/io/ably/pubsub/liveobjects/adapter/package-info.java new file mode 100644 index 000000000..a78782aa4 --- /dev/null +++ b/lib/src/main/java/io/ably/pubsub/liveobjects/adapter/package-info.java @@ -0,0 +1,10 @@ +/** + * Adapter layer bridging the path-based LiveObjects implementation to the core Ably client. + * {@link io.ably.pubsub.liveobjects.adapter.AblyClientAdapter} is the abstraction the implementation + * depends on; {@link io.ably.pubsub.liveobjects.adapter.Adapter} is the default implementation backed + * by an {@link io.ably.pubsub.realtime.PubSubRealtimeClient} client. + * + *

This package is intentionally independent of the legacy {@code io.ably.pubsub.objects} + * package so the path-based API can evolve on its own. + */ +package io.ably.pubsub.liveobjects.adapter; diff --git a/lib/src/main/java/io/ably/lib/liveobjects/instance/Instance.java b/lib/src/main/java/io/ably/pubsub/liveobjects/instance/Instance.java similarity index 91% rename from lib/src/main/java/io/ably/lib/liveobjects/instance/Instance.java rename to lib/src/main/java/io/ably/pubsub/liveobjects/instance/Instance.java index a364e9b3b..9d13f2c30 100644 --- a/lib/src/main/java/io/ably/lib/liveobjects/instance/Instance.java +++ b/lib/src/main/java/io/ably/pubsub/liveobjects/instance/Instance.java @@ -1,15 +1,15 @@ -package io.ably.lib.liveobjects.instance; +package io.ably.pubsub.liveobjects.instance; import com.google.gson.JsonElement; -import io.ably.lib.liveobjects.ValueType; -import io.ably.lib.liveobjects.instance.types.BinaryInstance; -import io.ably.lib.liveobjects.instance.types.BooleanInstance; -import io.ably.lib.liveobjects.instance.types.JsonArrayInstance; -import io.ably.lib.liveobjects.instance.types.JsonObjectInstance; -import io.ably.lib.liveobjects.instance.types.LiveCounterInstance; -import io.ably.lib.liveobjects.instance.types.LiveMapInstance; -import io.ably.lib.liveobjects.instance.types.NumberInstance; -import io.ably.lib.liveobjects.instance.types.StringInstance; +import io.ably.pubsub.liveobjects.ValueType; +import io.ably.pubsub.liveobjects.instance.types.BinaryInstance; +import io.ably.pubsub.liveobjects.instance.types.BooleanInstance; +import io.ably.pubsub.liveobjects.instance.types.JsonArrayInstance; +import io.ably.pubsub.liveobjects.instance.types.JsonObjectInstance; +import io.ably.pubsub.liveobjects.instance.types.LiveCounterInstance; +import io.ably.pubsub.liveobjects.instance.types.LiveMapInstance; +import io.ably.pubsub.liveobjects.instance.types.NumberInstance; +import io.ably.pubsub.liveobjects.instance.types.StringInstance; import org.jetbrains.annotations.NotNull; /** diff --git a/lib/src/main/java/io/ably/lib/liveobjects/instance/InstanceListener.java b/lib/src/main/java/io/ably/pubsub/liveobjects/instance/InstanceListener.java similarity index 72% rename from lib/src/main/java/io/ably/lib/liveobjects/instance/InstanceListener.java rename to lib/src/main/java/io/ably/pubsub/liveobjects/instance/InstanceListener.java index 942c0635b..29eaf01b5 100644 --- a/lib/src/main/java/io/ably/lib/liveobjects/instance/InstanceListener.java +++ b/lib/src/main/java/io/ably/pubsub/liveobjects/instance/InstanceListener.java @@ -1,7 +1,7 @@ -package io.ably.lib.liveobjects.instance; +package io.ably.pubsub.liveobjects.instance; -import io.ably.lib.liveobjects.instance.types.LiveCounterInstance; -import io.ably.lib.liveobjects.instance.types.LiveMapInstance; +import io.ably.pubsub.liveobjects.instance.types.LiveCounterInstance; +import io.ably.pubsub.liveobjects.instance.types.LiveMapInstance; import org.jetbrains.annotations.NotNull; /** diff --git a/lib/src/main/java/io/ably/lib/liveobjects/instance/InstanceSubscriptionEvent.java b/lib/src/main/java/io/ably/pubsub/liveobjects/instance/InstanceSubscriptionEvent.java similarity index 80% rename from lib/src/main/java/io/ably/lib/liveobjects/instance/InstanceSubscriptionEvent.java rename to lib/src/main/java/io/ably/pubsub/liveobjects/instance/InstanceSubscriptionEvent.java index db460035b..6b1c6180a 100644 --- a/lib/src/main/java/io/ably/lib/liveobjects/instance/InstanceSubscriptionEvent.java +++ b/lib/src/main/java/io/ably/pubsub/liveobjects/instance/InstanceSubscriptionEvent.java @@ -1,8 +1,8 @@ -package io.ably.lib.liveobjects.instance; +package io.ably.pubsub.liveobjects.instance; -import io.ably.lib.liveobjects.instance.types.LiveCounterInstance; -import io.ably.lib.liveobjects.instance.types.LiveMapInstance; -import io.ably.lib.liveobjects.message.ObjectMessage; +import io.ably.pubsub.liveobjects.instance.types.LiveCounterInstance; +import io.ably.pubsub.liveobjects.instance.types.LiveMapInstance; +import io.ably.pubsub.liveobjects.message.ObjectMessage; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; diff --git a/lib/src/main/java/io/ably/pubsub/liveobjects/instance/package-info.java b/lib/src/main/java/io/ably/pubsub/liveobjects/instance/package-info.java new file mode 100644 index 000000000..94ce54569 --- /dev/null +++ b/lib/src/main/java/io/ably/pubsub/liveobjects/instance/package-info.java @@ -0,0 +1,12 @@ +/** + * The identity-addressed view of the LiveObjects graph. + * {@link io.ably.pubsub.liveobjects.instance.Instance} wraps a specific resolved + * LiveObject or primitive value and dereferences it in O(1), following the + * object wherever it sits in the graph. Type-specific operations live on the + * sub-types in {@link io.ably.pubsub.liveobjects.instance.types}; instance + * subscriptions use {@link io.ably.pubsub.liveobjects.instance.InstanceListener} and + * {@link io.ably.pubsub.liveobjects.instance.InstanceSubscriptionEvent}. + * + *

Spec: RTINS1-RTINS16, RTTS7-RTTS9 + */ +package io.ably.pubsub.liveobjects.instance; diff --git a/lib/src/main/java/io/ably/lib/liveobjects/instance/types/BinaryInstance.java b/lib/src/main/java/io/ably/pubsub/liveobjects/instance/types/BinaryInstance.java similarity index 90% rename from lib/src/main/java/io/ably/lib/liveobjects/instance/types/BinaryInstance.java rename to lib/src/main/java/io/ably/pubsub/liveobjects/instance/types/BinaryInstance.java index e7564df31..054e2d606 100644 --- a/lib/src/main/java/io/ably/lib/liveobjects/instance/types/BinaryInstance.java +++ b/lib/src/main/java/io/ably/pubsub/liveobjects/instance/types/BinaryInstance.java @@ -1,7 +1,7 @@ -package io.ably.lib.liveobjects.instance.types; +package io.ably.pubsub.liveobjects.instance.types; import com.google.gson.JsonPrimitive; -import io.ably.lib.liveobjects.instance.Instance; +import io.ably.pubsub.liveobjects.instance.Instance; import org.jetbrains.annotations.NotNull; /** diff --git a/lib/src/main/java/io/ably/lib/liveobjects/instance/types/BooleanInstance.java b/lib/src/main/java/io/ably/pubsub/liveobjects/instance/types/BooleanInstance.java similarity index 90% rename from lib/src/main/java/io/ably/lib/liveobjects/instance/types/BooleanInstance.java rename to lib/src/main/java/io/ably/pubsub/liveobjects/instance/types/BooleanInstance.java index 90eebf425..0e9260a58 100644 --- a/lib/src/main/java/io/ably/lib/liveobjects/instance/types/BooleanInstance.java +++ b/lib/src/main/java/io/ably/pubsub/liveobjects/instance/types/BooleanInstance.java @@ -1,7 +1,7 @@ -package io.ably.lib.liveobjects.instance.types; +package io.ably.pubsub.liveobjects.instance.types; import com.google.gson.JsonPrimitive; -import io.ably.lib.liveobjects.instance.Instance; +import io.ably.pubsub.liveobjects.instance.Instance; import org.jetbrains.annotations.NotNull; /** diff --git a/lib/src/main/java/io/ably/lib/liveobjects/instance/types/JsonArrayInstance.java b/lib/src/main/java/io/ably/pubsub/liveobjects/instance/types/JsonArrayInstance.java similarity index 90% rename from lib/src/main/java/io/ably/lib/liveobjects/instance/types/JsonArrayInstance.java rename to lib/src/main/java/io/ably/pubsub/liveobjects/instance/types/JsonArrayInstance.java index ce916e907..310db9be2 100644 --- a/lib/src/main/java/io/ably/lib/liveobjects/instance/types/JsonArrayInstance.java +++ b/lib/src/main/java/io/ably/pubsub/liveobjects/instance/types/JsonArrayInstance.java @@ -1,7 +1,7 @@ -package io.ably.lib.liveobjects.instance.types; +package io.ably.pubsub.liveobjects.instance.types; import com.google.gson.JsonArray; -import io.ably.lib.liveobjects.instance.Instance; +import io.ably.pubsub.liveobjects.instance.Instance; import org.jetbrains.annotations.NotNull; /** diff --git a/lib/src/main/java/io/ably/lib/liveobjects/instance/types/JsonObjectInstance.java b/lib/src/main/java/io/ably/pubsub/liveobjects/instance/types/JsonObjectInstance.java similarity index 90% rename from lib/src/main/java/io/ably/lib/liveobjects/instance/types/JsonObjectInstance.java rename to lib/src/main/java/io/ably/pubsub/liveobjects/instance/types/JsonObjectInstance.java index 724fe5242..ec177a53e 100644 --- a/lib/src/main/java/io/ably/lib/liveobjects/instance/types/JsonObjectInstance.java +++ b/lib/src/main/java/io/ably/pubsub/liveobjects/instance/types/JsonObjectInstance.java @@ -1,7 +1,7 @@ -package io.ably.lib.liveobjects.instance.types; +package io.ably.pubsub.liveobjects.instance.types; import com.google.gson.JsonObject; -import io.ably.lib.liveobjects.instance.Instance; +import io.ably.pubsub.liveobjects.instance.Instance; import org.jetbrains.annotations.NotNull; /** diff --git a/lib/src/main/java/io/ably/lib/liveobjects/instance/types/LiveCounterInstance.java b/lib/src/main/java/io/ably/pubsub/liveobjects/instance/types/LiveCounterInstance.java similarity index 94% rename from lib/src/main/java/io/ably/lib/liveobjects/instance/types/LiveCounterInstance.java rename to lib/src/main/java/io/ably/pubsub/liveobjects/instance/types/LiveCounterInstance.java index dd2ba8a51..d3e6178e2 100644 --- a/lib/src/main/java/io/ably/lib/liveobjects/instance/types/LiveCounterInstance.java +++ b/lib/src/main/java/io/ably/pubsub/liveobjects/instance/types/LiveCounterInstance.java @@ -1,9 +1,9 @@ -package io.ably.lib.liveobjects.instance.types; +package io.ably.pubsub.liveobjects.instance.types; import com.google.gson.JsonPrimitive; -import io.ably.lib.liveobjects.instance.Instance; -import io.ably.lib.liveobjects.instance.InstanceListener; -import io.ably.lib.liveobjects.Subscription; +import io.ably.pubsub.liveobjects.instance.Instance; +import io.ably.pubsub.liveobjects.instance.InstanceListener; +import io.ably.pubsub.liveobjects.Subscription; import org.jetbrains.annotations.NonBlocking; import org.jetbrains.annotations.NotNull; diff --git a/lib/src/main/java/io/ably/lib/liveobjects/instance/types/LiveMapInstance.java b/lib/src/main/java/io/ably/pubsub/liveobjects/instance/types/LiveMapInstance.java similarity index 94% rename from lib/src/main/java/io/ably/lib/liveobjects/instance/types/LiveMapInstance.java rename to lib/src/main/java/io/ably/pubsub/liveobjects/instance/types/LiveMapInstance.java index 6e7c21e47..e19851f3f 100644 --- a/lib/src/main/java/io/ably/lib/liveobjects/instance/types/LiveMapInstance.java +++ b/lib/src/main/java/io/ably/pubsub/liveobjects/instance/types/LiveMapInstance.java @@ -1,10 +1,10 @@ -package io.ably.lib.liveobjects.instance.types; +package io.ably.pubsub.liveobjects.instance.types; import com.google.gson.JsonObject; -import io.ably.lib.liveobjects.instance.Instance; -import io.ably.lib.liveobjects.instance.InstanceListener; -import io.ably.lib.liveobjects.Subscription; -import io.ably.lib.liveobjects.value.LiveMapValue; +import io.ably.pubsub.liveobjects.instance.Instance; +import io.ably.pubsub.liveobjects.instance.InstanceListener; +import io.ably.pubsub.liveobjects.Subscription; +import io.ably.pubsub.liveobjects.value.LiveMapValue; import org.jetbrains.annotations.NonBlocking; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; diff --git a/lib/src/main/java/io/ably/lib/liveobjects/instance/types/NumberInstance.java b/lib/src/main/java/io/ably/pubsub/liveobjects/instance/types/NumberInstance.java similarity index 90% rename from lib/src/main/java/io/ably/lib/liveobjects/instance/types/NumberInstance.java rename to lib/src/main/java/io/ably/pubsub/liveobjects/instance/types/NumberInstance.java index f18cb3c74..764ef2860 100644 --- a/lib/src/main/java/io/ably/lib/liveobjects/instance/types/NumberInstance.java +++ b/lib/src/main/java/io/ably/pubsub/liveobjects/instance/types/NumberInstance.java @@ -1,7 +1,7 @@ -package io.ably.lib.liveobjects.instance.types; +package io.ably.pubsub.liveobjects.instance.types; import com.google.gson.JsonPrimitive; -import io.ably.lib.liveobjects.instance.Instance; +import io.ably.pubsub.liveobjects.instance.Instance; import org.jetbrains.annotations.NotNull; /** diff --git a/lib/src/main/java/io/ably/lib/liveobjects/instance/types/StringInstance.java b/lib/src/main/java/io/ably/pubsub/liveobjects/instance/types/StringInstance.java similarity index 90% rename from lib/src/main/java/io/ably/lib/liveobjects/instance/types/StringInstance.java rename to lib/src/main/java/io/ably/pubsub/liveobjects/instance/types/StringInstance.java index 680f0c3ae..e8c101380 100644 --- a/lib/src/main/java/io/ably/lib/liveobjects/instance/types/StringInstance.java +++ b/lib/src/main/java/io/ably/pubsub/liveobjects/instance/types/StringInstance.java @@ -1,7 +1,7 @@ -package io.ably.lib.liveobjects.instance.types; +package io.ably.pubsub.liveobjects.instance.types; import com.google.gson.JsonPrimitive; -import io.ably.lib.liveobjects.instance.Instance; +import io.ably.pubsub.liveobjects.instance.Instance; import org.jetbrains.annotations.NotNull; /** diff --git a/lib/src/main/java/io/ably/lib/liveobjects/instance/types/package-info.java b/lib/src/main/java/io/ably/pubsub/liveobjects/instance/types/package-info.java similarity index 59% rename from lib/src/main/java/io/ably/lib/liveobjects/instance/types/package-info.java rename to lib/src/main/java/io/ably/pubsub/liveobjects/instance/types/package-info.java index 651f45669..a4a6e25ad 100644 --- a/lib/src/main/java/io/ably/lib/liveobjects/instance/types/package-info.java +++ b/lib/src/main/java/io/ably/pubsub/liveobjects/instance/types/package-info.java @@ -1,11 +1,11 @@ /** * Type-specific {@code Instance} sub-types: the typed-SDK partition of instance - * operations. {@link io.ably.lib.liveobjects.instance.types.LiveMapInstance} + * operations. {@link io.ably.pubsub.liveobjects.instance.types.LiveMapInstance} * (RTTS10a) carries map reads, writes and subscribe, - * {@link io.ably.lib.liveobjects.instance.types.LiveCounterInstance} (RTTS10b) + * {@link io.ably.pubsub.liveobjects.instance.types.LiveCounterInstance} (RTTS10b) * carries counter operations and subscribe, and the six primitive sub-types * (RTTS10c) expose only a type-narrowed, non-null {@code value()}. * *

Spec: RTTS10 */ -package io.ably.lib.liveobjects.instance.types; +package io.ably.pubsub.liveobjects.instance.types; diff --git a/lib/src/main/java/io/ably/lib/liveobjects/message/CounterCreate.java b/lib/src/main/java/io/ably/pubsub/liveobjects/message/CounterCreate.java similarity index 93% rename from lib/src/main/java/io/ably/lib/liveobjects/message/CounterCreate.java rename to lib/src/main/java/io/ably/pubsub/liveobjects/message/CounterCreate.java index ffcdc73d0..1d02cea46 100644 --- a/lib/src/main/java/io/ably/lib/liveobjects/message/CounterCreate.java +++ b/lib/src/main/java/io/ably/pubsub/liveobjects/message/CounterCreate.java @@ -1,4 +1,4 @@ -package io.ably.lib.liveobjects.message; +package io.ably.pubsub.liveobjects.message; import org.jetbrains.annotations.Nullable; diff --git a/lib/src/main/java/io/ably/lib/liveobjects/message/CounterInc.java b/lib/src/main/java/io/ably/pubsub/liveobjects/message/CounterInc.java similarity index 93% rename from lib/src/main/java/io/ably/lib/liveobjects/message/CounterInc.java rename to lib/src/main/java/io/ably/pubsub/liveobjects/message/CounterInc.java index 8b8aafc70..3232507d8 100644 --- a/lib/src/main/java/io/ably/lib/liveobjects/message/CounterInc.java +++ b/lib/src/main/java/io/ably/pubsub/liveobjects/message/CounterInc.java @@ -1,4 +1,4 @@ -package io.ably.lib.liveobjects.message; +package io.ably.pubsub.liveobjects.message; import org.jetbrains.annotations.Nullable; diff --git a/lib/src/main/java/io/ably/lib/liveobjects/message/MapClear.java b/lib/src/main/java/io/ably/pubsub/liveobjects/message/MapClear.java similarity index 88% rename from lib/src/main/java/io/ably/lib/liveobjects/message/MapClear.java rename to lib/src/main/java/io/ably/pubsub/liveobjects/message/MapClear.java index 29c9092dc..2358f406b 100644 --- a/lib/src/main/java/io/ably/lib/liveobjects/message/MapClear.java +++ b/lib/src/main/java/io/ably/pubsub/liveobjects/message/MapClear.java @@ -1,4 +1,4 @@ -package io.ably.lib.liveobjects.message; +package io.ably.pubsub.liveobjects.message; /** * Payload of a {@link ObjectOperationAction#MAP_CLEAR} operation. This type diff --git a/lib/src/main/java/io/ably/lib/liveobjects/message/MapCreate.java b/lib/src/main/java/io/ably/pubsub/liveobjects/message/MapCreate.java similarity index 94% rename from lib/src/main/java/io/ably/lib/liveobjects/message/MapCreate.java rename to lib/src/main/java/io/ably/pubsub/liveobjects/message/MapCreate.java index fcd7fc539..18edc1b55 100644 --- a/lib/src/main/java/io/ably/lib/liveobjects/message/MapCreate.java +++ b/lib/src/main/java/io/ably/pubsub/liveobjects/message/MapCreate.java @@ -1,4 +1,4 @@ -package io.ably.lib.liveobjects.message; +package io.ably.pubsub.liveobjects.message; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Unmodifiable; diff --git a/lib/src/main/java/io/ably/lib/liveobjects/message/MapRemove.java b/lib/src/main/java/io/ably/pubsub/liveobjects/message/MapRemove.java similarity index 89% rename from lib/src/main/java/io/ably/lib/liveobjects/message/MapRemove.java rename to lib/src/main/java/io/ably/pubsub/liveobjects/message/MapRemove.java index fccb67464..64d59efd8 100644 --- a/lib/src/main/java/io/ably/lib/liveobjects/message/MapRemove.java +++ b/lib/src/main/java/io/ably/pubsub/liveobjects/message/MapRemove.java @@ -1,4 +1,4 @@ -package io.ably.lib.liveobjects.message; +package io.ably.pubsub.liveobjects.message; import org.jetbrains.annotations.NotNull; diff --git a/lib/src/main/java/io/ably/lib/liveobjects/message/MapSet.java b/lib/src/main/java/io/ably/pubsub/liveobjects/message/MapSet.java similarity index 92% rename from lib/src/main/java/io/ably/lib/liveobjects/message/MapSet.java rename to lib/src/main/java/io/ably/pubsub/liveobjects/message/MapSet.java index 6b63e88cf..995e81e28 100644 --- a/lib/src/main/java/io/ably/lib/liveobjects/message/MapSet.java +++ b/lib/src/main/java/io/ably/pubsub/liveobjects/message/MapSet.java @@ -1,4 +1,4 @@ -package io.ably.lib.liveobjects.message; +package io.ably.pubsub.liveobjects.message; import org.jetbrains.annotations.NotNull; diff --git a/lib/src/main/java/io/ably/lib/liveobjects/message/ObjectData.java b/lib/src/main/java/io/ably/pubsub/liveobjects/message/ObjectData.java similarity index 97% rename from lib/src/main/java/io/ably/lib/liveobjects/message/ObjectData.java rename to lib/src/main/java/io/ably/pubsub/liveobjects/message/ObjectData.java index b98e53920..83b3bc625 100644 --- a/lib/src/main/java/io/ably/lib/liveobjects/message/ObjectData.java +++ b/lib/src/main/java/io/ably/pubsub/liveobjects/message/ObjectData.java @@ -1,4 +1,4 @@ -package io.ably.lib.liveobjects.message; +package io.ably.pubsub.liveobjects.message; import com.google.gson.JsonElement; import org.jetbrains.annotations.Nullable; diff --git a/lib/src/main/java/io/ably/lib/liveobjects/message/ObjectDelete.java b/lib/src/main/java/io/ably/pubsub/liveobjects/message/ObjectDelete.java similarity index 88% rename from lib/src/main/java/io/ably/lib/liveobjects/message/ObjectDelete.java rename to lib/src/main/java/io/ably/pubsub/liveobjects/message/ObjectDelete.java index 1f8c8c671..1698787bd 100644 --- a/lib/src/main/java/io/ably/lib/liveobjects/message/ObjectDelete.java +++ b/lib/src/main/java/io/ably/pubsub/liveobjects/message/ObjectDelete.java @@ -1,4 +1,4 @@ -package io.ably.lib.liveobjects.message; +package io.ably.pubsub.liveobjects.message; /** * Payload of an {@link ObjectOperationAction#OBJECT_DELETE} operation. This type diff --git a/lib/src/main/java/io/ably/lib/liveobjects/message/ObjectMessage.java b/lib/src/main/java/io/ably/pubsub/liveobjects/message/ObjectMessage.java similarity index 92% rename from lib/src/main/java/io/ably/lib/liveobjects/message/ObjectMessage.java rename to lib/src/main/java/io/ably/pubsub/liveobjects/message/ObjectMessage.java index 3a2513643..695610024 100644 --- a/lib/src/main/java/io/ably/lib/liveobjects/message/ObjectMessage.java +++ b/lib/src/main/java/io/ably/pubsub/liveobjects/message/ObjectMessage.java @@ -1,4 +1,4 @@ -package io.ably.lib.liveobjects.message; +package io.ably.pubsub.liveobjects.message; import com.google.gson.JsonObject; import org.jetbrains.annotations.NotNull; @@ -7,14 +7,14 @@ /** * The user-facing representation of an inbound object message that carried an operation. * It is delivered to subscription listeners (see - * {@link io.ably.lib.liveobjects.path.PathObjectSubscriptionEvent} and - * {@link io.ably.lib.liveobjects.instance.InstanceSubscriptionEvent}) so that user code can + * {@link io.ably.pubsub.liveobjects.path.PathObjectSubscriptionEvent} and + * {@link io.ably.pubsub.liveobjects.instance.InstanceSubscriptionEvent}) so that user code can * inspect the metadata of the message that triggered an object change. * *

An {@code ObjectMessage} always carries an {@link #getOperation() operation}; object * messages without an operation (e.g. sync state messages) are never surfaced to users. * - *

This type is the entry point of the {@code io.ably.lib.object.message} package; + *

This type is the entry point of the {@code io.ably.pubsub.object.message} package; * all sibling types are reached by walking its properties: * *

{@code
diff --git a/lib/src/main/java/io/ably/lib/liveobjects/message/ObjectOperation.java b/lib/src/main/java/io/ably/pubsub/liveobjects/message/ObjectOperation.java
similarity index 98%
rename from lib/src/main/java/io/ably/lib/liveobjects/message/ObjectOperation.java
rename to lib/src/main/java/io/ably/pubsub/liveobjects/message/ObjectOperation.java
index d4df9fb00..eb6795ea4 100644
--- a/lib/src/main/java/io/ably/lib/liveobjects/message/ObjectOperation.java
+++ b/lib/src/main/java/io/ably/pubsub/liveobjects/message/ObjectOperation.java
@@ -1,4 +1,4 @@
-package io.ably.lib.liveobjects.message;
+package io.ably.pubsub.liveobjects.message;
 
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
diff --git a/lib/src/main/java/io/ably/lib/liveobjects/message/ObjectOperationAction.java b/lib/src/main/java/io/ably/pubsub/liveobjects/message/ObjectOperationAction.java
similarity index 95%
rename from lib/src/main/java/io/ably/lib/liveobjects/message/ObjectOperationAction.java
rename to lib/src/main/java/io/ably/pubsub/liveobjects/message/ObjectOperationAction.java
index 002f289d4..424bd4596 100644
--- a/lib/src/main/java/io/ably/lib/liveobjects/message/ObjectOperationAction.java
+++ b/lib/src/main/java/io/ably/pubsub/liveobjects/message/ObjectOperationAction.java
@@ -1,4 +1,4 @@
-package io.ably.lib.liveobjects.message;
+package io.ably.pubsub.liveobjects.message;
 
 /**
  * The action of an {@link ObjectOperation}, defining the type of operation that was
diff --git a/lib/src/main/java/io/ably/lib/liveobjects/message/ObjectsMapEntry.java b/lib/src/main/java/io/ably/pubsub/liveobjects/message/ObjectsMapEntry.java
similarity index 96%
rename from lib/src/main/java/io/ably/lib/liveobjects/message/ObjectsMapEntry.java
rename to lib/src/main/java/io/ably/pubsub/liveobjects/message/ObjectsMapEntry.java
index 3252042d1..b3fb7ede7 100644
--- a/lib/src/main/java/io/ably/lib/liveobjects/message/ObjectsMapEntry.java
+++ b/lib/src/main/java/io/ably/pubsub/liveobjects/message/ObjectsMapEntry.java
@@ -1,4 +1,4 @@
-package io.ably.lib.liveobjects.message;
+package io.ably.pubsub.liveobjects.message;
 
 import org.jetbrains.annotations.Nullable;
 
diff --git a/lib/src/main/java/io/ably/lib/liveobjects/message/ObjectsMapSemantics.java b/lib/src/main/java/io/ably/pubsub/liveobjects/message/ObjectsMapSemantics.java
similarity index 88%
rename from lib/src/main/java/io/ably/lib/liveobjects/message/ObjectsMapSemantics.java
rename to lib/src/main/java/io/ably/pubsub/liveobjects/message/ObjectsMapSemantics.java
index 1fcb7f2aa..329e3028b 100644
--- a/lib/src/main/java/io/ably/lib/liveobjects/message/ObjectsMapSemantics.java
+++ b/lib/src/main/java/io/ably/pubsub/liveobjects/message/ObjectsMapSemantics.java
@@ -1,4 +1,4 @@
-package io.ably.lib.liveobjects.message;
+package io.ably.pubsub.liveobjects.message;
 
 /**
  * The conflict-resolution semantics used by a {@code LiveMap} object.
diff --git a/lib/src/main/java/io/ably/lib/liveobjects/message/package-info.java b/lib/src/main/java/io/ably/pubsub/liveobjects/message/package-info.java
similarity index 89%
rename from lib/src/main/java/io/ably/lib/liveobjects/message/package-info.java
rename to lib/src/main/java/io/ably/pubsub/liveobjects/message/package-info.java
index f3f7c246e..932b05fa8 100644
--- a/lib/src/main/java/io/ably/lib/liveobjects/message/package-info.java
+++ b/lib/src/main/java/io/ably/pubsub/liveobjects/message/package-info.java
@@ -2,7 +2,7 @@
  * User-facing object message metadata, delivered to subscription listeners so
  * that user code can inspect the operation that triggered an object change.
  *
- * 

{@link io.ably.lib.liveobjects.message.ObjectMessage} is the single entry point + *

{@link io.ably.pubsub.liveobjects.message.ObjectMessage} is the single entry point * of this package; every other type is reached by walking its properties: * *

{@code
@@ -23,4 +23,4 @@
  *
  * 

Spec: PAOM1-PAOM3, PAOOP1-PAOOP3 */ -package io.ably.lib.liveobjects.message; +package io.ably.pubsub.liveobjects.message; diff --git a/lib/src/main/java/io/ably/pubsub/liveobjects/package-info.java b/lib/src/main/java/io/ably/pubsub/liveobjects/package-info.java new file mode 100644 index 000000000..7057189f8 --- /dev/null +++ b/lib/src/main/java/io/ably/pubsub/liveobjects/package-info.java @@ -0,0 +1,17 @@ +/** + * The public, strongly-typed LiveObjects API: path-based and instance-based views + * over the objects graph on a channel. + * + *

This root package holds the types shared by both view hierarchies: + * {@link io.ably.pubsub.liveobjects.ValueType} (the categories a resolved value may have) + * and {@link io.ably.pubsub.liveobjects.Subscription} (the handle returned by every + * {@code subscribe} operation). The hierarchies themselves live in + * {@link io.ably.pubsub.liveobjects.path} (lazy, path-addressed references) and + * {@link io.ably.pubsub.liveobjects.instance} (O(1), identity-addressed references); + * message metadata delivered to subscription listeners lives in + * {@link io.ably.pubsub.liveobjects.message}, and write-side value types in + * {@link io.ably.pubsub.liveobjects.value}. + * + *

Spec: RTTS1-RTTS10 (typed-SDK public API partition) + */ +package io.ably.pubsub.liveobjects; diff --git a/lib/src/main/java/io/ably/lib/liveobjects/path/PathObject.java b/lib/src/main/java/io/ably/pubsub/liveobjects/path/PathObject.java similarity index 92% rename from lib/src/main/java/io/ably/lib/liveobjects/path/PathObject.java rename to lib/src/main/java/io/ably/pubsub/liveobjects/path/PathObject.java index 8a6ead714..d1f0ede5e 100644 --- a/lib/src/main/java/io/ably/lib/liveobjects/path/PathObject.java +++ b/lib/src/main/java/io/ably/pubsub/liveobjects/path/PathObject.java @@ -1,17 +1,17 @@ -package io.ably.lib.liveobjects.path; +package io.ably.pubsub.liveobjects.path; import com.google.gson.JsonElement; -import io.ably.lib.liveobjects.ValueType; -import io.ably.lib.liveobjects.instance.Instance; -import io.ably.lib.liveobjects.path.types.BinaryPathObject; -import io.ably.lib.liveobjects.path.types.BooleanPathObject; -import io.ably.lib.liveobjects.path.types.JsonArrayPathObject; -import io.ably.lib.liveobjects.path.types.JsonObjectPathObject; -import io.ably.lib.liveobjects.path.types.LiveCounterPathObject; -import io.ably.lib.liveobjects.path.types.LiveMapPathObject; -import io.ably.lib.liveobjects.path.types.NumberPathObject; -import io.ably.lib.liveobjects.path.types.StringPathObject; -import io.ably.lib.liveobjects.Subscription; +import io.ably.pubsub.liveobjects.ValueType; +import io.ably.pubsub.liveobjects.instance.Instance; +import io.ably.pubsub.liveobjects.path.types.BinaryPathObject; +import io.ably.pubsub.liveobjects.path.types.BooleanPathObject; +import io.ably.pubsub.liveobjects.path.types.JsonArrayPathObject; +import io.ably.pubsub.liveobjects.path.types.JsonObjectPathObject; +import io.ably.pubsub.liveobjects.path.types.LiveCounterPathObject; +import io.ably.pubsub.liveobjects.path.types.LiveMapPathObject; +import io.ably.pubsub.liveobjects.path.types.NumberPathObject; +import io.ably.pubsub.liveobjects.path.types.StringPathObject; +import io.ably.pubsub.liveobjects.Subscription; import org.jetbrains.annotations.NonBlocking; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; diff --git a/lib/src/main/java/io/ably/lib/liveobjects/path/PathObjectListener.java b/lib/src/main/java/io/ably/pubsub/liveobjects/path/PathObjectListener.java similarity index 93% rename from lib/src/main/java/io/ably/lib/liveobjects/path/PathObjectListener.java rename to lib/src/main/java/io/ably/pubsub/liveobjects/path/PathObjectListener.java index 48bca1c72..bc9dbf831 100644 --- a/lib/src/main/java/io/ably/lib/liveobjects/path/PathObjectListener.java +++ b/lib/src/main/java/io/ably/pubsub/liveobjects/path/PathObjectListener.java @@ -1,4 +1,4 @@ -package io.ably.lib.liveobjects.path; +package io.ably.pubsub.liveobjects.path; import org.jetbrains.annotations.NotNull; diff --git a/lib/src/main/java/io/ably/lib/liveobjects/path/PathObjectSubscriptionEvent.java b/lib/src/main/java/io/ably/pubsub/liveobjects/path/PathObjectSubscriptionEvent.java similarity index 90% rename from lib/src/main/java/io/ably/lib/liveobjects/path/PathObjectSubscriptionEvent.java rename to lib/src/main/java/io/ably/pubsub/liveobjects/path/PathObjectSubscriptionEvent.java index 7fd978de9..c94311b8c 100644 --- a/lib/src/main/java/io/ably/lib/liveobjects/path/PathObjectSubscriptionEvent.java +++ b/lib/src/main/java/io/ably/pubsub/liveobjects/path/PathObjectSubscriptionEvent.java @@ -1,6 +1,6 @@ -package io.ably.lib.liveobjects.path; +package io.ably.pubsub.liveobjects.path; -import io.ably.lib.liveobjects.message.ObjectMessage; +import io.ably.pubsub.liveobjects.message.ObjectMessage; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; diff --git a/lib/src/main/java/io/ably/lib/liveobjects/path/PathObjectSubscriptionOptions.java b/lib/src/main/java/io/ably/pubsub/liveobjects/path/PathObjectSubscriptionOptions.java similarity index 93% rename from lib/src/main/java/io/ably/lib/liveobjects/path/PathObjectSubscriptionOptions.java rename to lib/src/main/java/io/ably/pubsub/liveobjects/path/PathObjectSubscriptionOptions.java index df9b5a9fa..7b48d719a 100644 --- a/lib/src/main/java/io/ably/lib/liveobjects/path/PathObjectSubscriptionOptions.java +++ b/lib/src/main/java/io/ably/pubsub/liveobjects/path/PathObjectSubscriptionOptions.java @@ -1,7 +1,7 @@ -package io.ably.lib.liveobjects.path; +package io.ably.pubsub.liveobjects.path; -import io.ably.lib.types.AblyException; -import io.ably.lib.types.ErrorInfo; +import io.ably.pubsub.types.AblyException; +import io.ably.pubsub.types.ErrorInfo; import org.jetbrains.annotations.Nullable; /** diff --git a/lib/src/main/java/io/ably/pubsub/liveobjects/path/package-info.java b/lib/src/main/java/io/ably/pubsub/liveobjects/path/package-info.java new file mode 100644 index 000000000..99d7db2d4 --- /dev/null +++ b/lib/src/main/java/io/ably/pubsub/liveobjects/path/package-info.java @@ -0,0 +1,13 @@ +/** + * The path-addressed view of the LiveObjects graph. + * {@link io.ably.pubsub.liveobjects.path.PathObject} stores a path from the channel's + * root {@code LiveMap} and re-resolves it lazily on every call, so a reference + * survives object replacement at its path. Type-specific operations live on the + * sub-types in {@link io.ably.pubsub.liveobjects.path.types}; path-based subscriptions + * use {@link io.ably.pubsub.liveobjects.path.PathObjectListener}, + * {@link io.ably.pubsub.liveobjects.path.PathObjectSubscriptionEvent} and + * {@link io.ably.pubsub.liveobjects.path.PathObjectSubscriptionOptions}. + * + *

Spec: RTPO1-RTPO19, RTTS3-RTTS5 + */ +package io.ably.pubsub.liveobjects.path; diff --git a/lib/src/main/java/io/ably/lib/liveobjects/path/types/BinaryPathObject.java b/lib/src/main/java/io/ably/pubsub/liveobjects/path/types/BinaryPathObject.java similarity index 89% rename from lib/src/main/java/io/ably/lib/liveobjects/path/types/BinaryPathObject.java rename to lib/src/main/java/io/ably/pubsub/liveobjects/path/types/BinaryPathObject.java index 76e5af7bf..641e89c3d 100644 --- a/lib/src/main/java/io/ably/lib/liveobjects/path/types/BinaryPathObject.java +++ b/lib/src/main/java/io/ably/pubsub/liveobjects/path/types/BinaryPathObject.java @@ -1,6 +1,6 @@ -package io.ably.lib.liveobjects.path.types; +package io.ably.pubsub.liveobjects.path.types; -import io.ably.lib.liveobjects.path.PathObject; +import io.ably.pubsub.liveobjects.path.PathObject; import org.jetbrains.annotations.Nullable; /** diff --git a/lib/src/main/java/io/ably/lib/liveobjects/path/types/BooleanPathObject.java b/lib/src/main/java/io/ably/pubsub/liveobjects/path/types/BooleanPathObject.java similarity index 89% rename from lib/src/main/java/io/ably/lib/liveobjects/path/types/BooleanPathObject.java rename to lib/src/main/java/io/ably/pubsub/liveobjects/path/types/BooleanPathObject.java index 632ac6680..f07a62220 100644 --- a/lib/src/main/java/io/ably/lib/liveobjects/path/types/BooleanPathObject.java +++ b/lib/src/main/java/io/ably/pubsub/liveobjects/path/types/BooleanPathObject.java @@ -1,6 +1,6 @@ -package io.ably.lib.liveobjects.path.types; +package io.ably.pubsub.liveobjects.path.types; -import io.ably.lib.liveobjects.path.PathObject; +import io.ably.pubsub.liveobjects.path.PathObject; import org.jetbrains.annotations.Nullable; /** diff --git a/lib/src/main/java/io/ably/lib/liveobjects/path/types/JsonArrayPathObject.java b/lib/src/main/java/io/ably/pubsub/liveobjects/path/types/JsonArrayPathObject.java similarity index 89% rename from lib/src/main/java/io/ably/lib/liveobjects/path/types/JsonArrayPathObject.java rename to lib/src/main/java/io/ably/pubsub/liveobjects/path/types/JsonArrayPathObject.java index 97b2462e6..9cebf7ca7 100644 --- a/lib/src/main/java/io/ably/lib/liveobjects/path/types/JsonArrayPathObject.java +++ b/lib/src/main/java/io/ably/pubsub/liveobjects/path/types/JsonArrayPathObject.java @@ -1,7 +1,7 @@ -package io.ably.lib.liveobjects.path.types; +package io.ably.pubsub.liveobjects.path.types; import com.google.gson.JsonArray; -import io.ably.lib.liveobjects.path.PathObject; +import io.ably.pubsub.liveobjects.path.PathObject; import org.jetbrains.annotations.Nullable; /** diff --git a/lib/src/main/java/io/ably/lib/liveobjects/path/types/JsonObjectPathObject.java b/lib/src/main/java/io/ably/pubsub/liveobjects/path/types/JsonObjectPathObject.java similarity index 90% rename from lib/src/main/java/io/ably/lib/liveobjects/path/types/JsonObjectPathObject.java rename to lib/src/main/java/io/ably/pubsub/liveobjects/path/types/JsonObjectPathObject.java index 4edc5c584..77c116365 100644 --- a/lib/src/main/java/io/ably/lib/liveobjects/path/types/JsonObjectPathObject.java +++ b/lib/src/main/java/io/ably/pubsub/liveobjects/path/types/JsonObjectPathObject.java @@ -1,7 +1,7 @@ -package io.ably.lib.liveobjects.path.types; +package io.ably.pubsub.liveobjects.path.types; import com.google.gson.JsonObject; -import io.ably.lib.liveobjects.path.PathObject; +import io.ably.pubsub.liveobjects.path.PathObject; import org.jetbrains.annotations.Nullable; /** diff --git a/lib/src/main/java/io/ably/lib/liveobjects/path/types/LiveCounterPathObject.java b/lib/src/main/java/io/ably/pubsub/liveobjects/path/types/LiveCounterPathObject.java similarity index 96% rename from lib/src/main/java/io/ably/lib/liveobjects/path/types/LiveCounterPathObject.java rename to lib/src/main/java/io/ably/pubsub/liveobjects/path/types/LiveCounterPathObject.java index fb8eb87d3..f2e8016a9 100644 --- a/lib/src/main/java/io/ably/lib/liveobjects/path/types/LiveCounterPathObject.java +++ b/lib/src/main/java/io/ably/pubsub/liveobjects/path/types/LiveCounterPathObject.java @@ -1,6 +1,6 @@ -package io.ably.lib.liveobjects.path.types; +package io.ably.pubsub.liveobjects.path.types; -import io.ably.lib.liveobjects.path.PathObject; +import io.ably.pubsub.liveobjects.path.PathObject; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; diff --git a/lib/src/main/java/io/ably/lib/liveobjects/path/types/LiveMapPathObject.java b/lib/src/main/java/io/ably/pubsub/liveobjects/path/types/LiveMapPathObject.java similarity index 97% rename from lib/src/main/java/io/ably/lib/liveobjects/path/types/LiveMapPathObject.java rename to lib/src/main/java/io/ably/pubsub/liveobjects/path/types/LiveMapPathObject.java index cf35e553f..6cef8244e 100644 --- a/lib/src/main/java/io/ably/lib/liveobjects/path/types/LiveMapPathObject.java +++ b/lib/src/main/java/io/ably/pubsub/liveobjects/path/types/LiveMapPathObject.java @@ -1,7 +1,7 @@ -package io.ably.lib.liveobjects.path.types; +package io.ably.pubsub.liveobjects.path.types; -import io.ably.lib.liveobjects.path.PathObject; -import io.ably.lib.liveobjects.value.LiveMapValue; +import io.ably.pubsub.liveobjects.path.PathObject; +import io.ably.pubsub.liveobjects.value.LiveMapValue; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Unmodifiable; diff --git a/lib/src/main/java/io/ably/lib/liveobjects/path/types/NumberPathObject.java b/lib/src/main/java/io/ably/pubsub/liveobjects/path/types/NumberPathObject.java similarity index 89% rename from lib/src/main/java/io/ably/lib/liveobjects/path/types/NumberPathObject.java rename to lib/src/main/java/io/ably/pubsub/liveobjects/path/types/NumberPathObject.java index e1b53d899..4f45f41aa 100644 --- a/lib/src/main/java/io/ably/lib/liveobjects/path/types/NumberPathObject.java +++ b/lib/src/main/java/io/ably/pubsub/liveobjects/path/types/NumberPathObject.java @@ -1,6 +1,6 @@ -package io.ably.lib.liveobjects.path.types; +package io.ably.pubsub.liveobjects.path.types; -import io.ably.lib.liveobjects.path.PathObject; +import io.ably.pubsub.liveobjects.path.PathObject; import org.jetbrains.annotations.Nullable; /** diff --git a/lib/src/main/java/io/ably/lib/liveobjects/path/types/StringPathObject.java b/lib/src/main/java/io/ably/pubsub/liveobjects/path/types/StringPathObject.java similarity index 89% rename from lib/src/main/java/io/ably/lib/liveobjects/path/types/StringPathObject.java rename to lib/src/main/java/io/ably/pubsub/liveobjects/path/types/StringPathObject.java index bd524d773..4fc607b9f 100644 --- a/lib/src/main/java/io/ably/lib/liveobjects/path/types/StringPathObject.java +++ b/lib/src/main/java/io/ably/pubsub/liveobjects/path/types/StringPathObject.java @@ -1,6 +1,6 @@ -package io.ably.lib.liveobjects.path.types; +package io.ably.pubsub.liveobjects.path.types; -import io.ably.lib.liveobjects.path.PathObject; +import io.ably.pubsub.liveobjects.path.PathObject; import org.jetbrains.annotations.Nullable; /** diff --git a/lib/src/main/java/io/ably/lib/liveobjects/path/types/package-info.java b/lib/src/main/java/io/ably/pubsub/liveobjects/path/types/package-info.java similarity index 53% rename from lib/src/main/java/io/ably/lib/liveobjects/path/types/package-info.java rename to lib/src/main/java/io/ably/pubsub/liveobjects/path/types/package-info.java index 1575cfabc..8d82d7b45 100644 --- a/lib/src/main/java/io/ably/lib/liveobjects/path/types/package-info.java +++ b/lib/src/main/java/io/ably/pubsub/liveobjects/path/types/package-info.java @@ -1,11 +1,11 @@ /** * Type-specific {@code PathObject} sub-types: the typed-SDK partition of path - * operations. {@link io.ably.lib.liveobjects.path.types.LiveMapPathObject} (RTTS6a) + * operations. {@link io.ably.pubsub.liveobjects.path.types.LiveMapPathObject} (RTTS6a) * carries map navigation and writes, - * {@link io.ably.lib.liveobjects.path.types.LiveCounterPathObject} (RTTS6b) carries + * {@link io.ably.pubsub.liveobjects.path.types.LiveCounterPathObject} (RTTS6b) carries * counter operations, and the six primitive sub-types (RTTS6c) expose only a * type-narrowed {@code value()}. * *

Spec: RTTS6 */ -package io.ably.lib.liveobjects.path.types; +package io.ably.pubsub.liveobjects.path.types; diff --git a/lib/src/main/java/io/ably/lib/liveobjects/serialization/ObjectJsonSerializer.java b/lib/src/main/java/io/ably/pubsub/liveobjects/serialization/ObjectJsonSerializer.java similarity index 94% rename from lib/src/main/java/io/ably/lib/liveobjects/serialization/ObjectJsonSerializer.java rename to lib/src/main/java/io/ably/pubsub/liveobjects/serialization/ObjectJsonSerializer.java index c6f95d200..170f8ba0a 100644 --- a/lib/src/main/java/io/ably/lib/liveobjects/serialization/ObjectJsonSerializer.java +++ b/lib/src/main/java/io/ably/pubsub/liveobjects/serialization/ObjectJsonSerializer.java @@ -1,4 +1,4 @@ -package io.ably.lib.liveobjects.serialization; +package io.ably.pubsub.liveobjects.serialization; import com.google.gson.JsonDeserializationContext; import com.google.gson.JsonDeserializer; @@ -7,7 +7,7 @@ import com.google.gson.JsonParseException; import com.google.gson.JsonSerializationContext; import com.google.gson.JsonSerializer; -import io.ably.lib.util.Log; +import io.ably.pubsub.util.Log; import java.lang.reflect.Type; diff --git a/lib/src/main/java/io/ably/lib/liveobjects/serialization/ObjectSerializer.java b/lib/src/main/java/io/ably/pubsub/liveobjects/serialization/ObjectSerializer.java similarity index 96% rename from lib/src/main/java/io/ably/lib/liveobjects/serialization/ObjectSerializer.java rename to lib/src/main/java/io/ably/pubsub/liveobjects/serialization/ObjectSerializer.java index c5b6abcf3..6ab95444b 100644 --- a/lib/src/main/java/io/ably/lib/liveobjects/serialization/ObjectSerializer.java +++ b/lib/src/main/java/io/ably/pubsub/liveobjects/serialization/ObjectSerializer.java @@ -1,7 +1,7 @@ -package io.ably.lib.liveobjects.serialization; +package io.ably.pubsub.liveobjects.serialization; import com.google.gson.JsonArray; -import io.ably.lib.util.Log; +import io.ably.pubsub.util.Log; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.msgpack.core.MessagePacker; @@ -70,7 +70,7 @@ static ObjectSerializer tryGet() { */ final class Holder { private static final String TAG = ObjectSerializer.Holder.class.getName(); - private static final String IMPLEMENTATION_CLASS = "io.ably.lib.liveobjects.serialization.DefaultObjectsSerializer"; + private static final String IMPLEMENTATION_CLASS = "io.ably.pubsub.liveobjects.serialization.DefaultObjectsSerializer"; private static volatile ObjectSerializer objectsSerializer; private Holder() {} diff --git a/lib/src/main/java/io/ably/lib/liveobjects/state/ObjectStateChange.java b/lib/src/main/java/io/ably/pubsub/liveobjects/state/ObjectStateChange.java similarity index 95% rename from lib/src/main/java/io/ably/lib/liveobjects/state/ObjectStateChange.java rename to lib/src/main/java/io/ably/pubsub/liveobjects/state/ObjectStateChange.java index d6bb65385..bbd57a141 100644 --- a/lib/src/main/java/io/ably/lib/liveobjects/state/ObjectStateChange.java +++ b/lib/src/main/java/io/ably/pubsub/liveobjects/state/ObjectStateChange.java @@ -1,6 +1,6 @@ -package io.ably.lib.liveobjects.state; +package io.ably.pubsub.liveobjects.state; -import io.ably.lib.liveobjects.Subscription; +import io.ably.pubsub.liveobjects.Subscription; import org.jetbrains.annotations.NonBlocking; import org.jetbrains.annotations.NotNull; diff --git a/lib/src/main/java/io/ably/lib/liveobjects/state/ObjectStateEvent.java b/lib/src/main/java/io/ably/pubsub/liveobjects/state/ObjectStateEvent.java similarity index 92% rename from lib/src/main/java/io/ably/lib/liveobjects/state/ObjectStateEvent.java rename to lib/src/main/java/io/ably/pubsub/liveobjects/state/ObjectStateEvent.java index 053d26116..6668c3d4b 100644 --- a/lib/src/main/java/io/ably/lib/liveobjects/state/ObjectStateEvent.java +++ b/lib/src/main/java/io/ably/pubsub/liveobjects/state/ObjectStateEvent.java @@ -1,4 +1,4 @@ -package io.ably.lib.liveobjects.state; +package io.ably.pubsub.liveobjects.state; /** * Represents the synchronization state of Ably Objects. diff --git a/lib/src/main/java/io/ably/lib/liveobjects/value/LiveCounter.java b/lib/src/main/java/io/ably/pubsub/liveobjects/value/LiveCounter.java similarity index 96% rename from lib/src/main/java/io/ably/lib/liveobjects/value/LiveCounter.java rename to lib/src/main/java/io/ably/pubsub/liveobjects/value/LiveCounter.java index 1581d2d78..746d03da8 100644 --- a/lib/src/main/java/io/ably/lib/liveobjects/value/LiveCounter.java +++ b/lib/src/main/java/io/ably/pubsub/liveobjects/value/LiveCounter.java @@ -1,4 +1,4 @@ -package io.ably.lib.liveobjects.value; +package io.ably.pubsub.liveobjects.value; import org.jetbrains.annotations.NotNull; @@ -23,7 +23,7 @@ */ public abstract class LiveCounter { - private static final String IMPLEMENTATION_CLASS = "io.ably.lib.liveobjects.value.livecounter.DefaultLiveCounter"; + private static final String IMPLEMENTATION_CLASS = "io.ably.pubsub.liveobjects.value.livecounter.DefaultLiveCounter"; /** * Extended by the LiveObjects implementation; not intended for diff --git a/lib/src/main/java/io/ably/lib/liveobjects/value/LiveMap.java b/lib/src/main/java/io/ably/pubsub/liveobjects/value/LiveMap.java similarity index 96% rename from lib/src/main/java/io/ably/lib/liveobjects/value/LiveMap.java rename to lib/src/main/java/io/ably/pubsub/liveobjects/value/LiveMap.java index 35fed8631..b19d7ee6b 100644 --- a/lib/src/main/java/io/ably/lib/liveobjects/value/LiveMap.java +++ b/lib/src/main/java/io/ably/pubsub/liveobjects/value/LiveMap.java @@ -1,4 +1,4 @@ -package io.ably.lib.liveobjects.value; +package io.ably.pubsub.liveobjects.value; import org.jetbrains.annotations.NotNull; @@ -26,7 +26,7 @@ */ public abstract class LiveMap { - private static final String IMPLEMENTATION_CLASS = "io.ably.lib.liveobjects.value.livemap.DefaultLiveMap"; + private static final String IMPLEMENTATION_CLASS = "io.ably.pubsub.liveobjects.value.livemap.DefaultLiveMap"; /** * Extended by the LiveObjects implementation; not intended for diff --git a/lib/src/main/java/io/ably/lib/liveobjects/value/LiveMapValue.java b/lib/src/main/java/io/ably/pubsub/liveobjects/value/LiveMapValue.java similarity index 99% rename from lib/src/main/java/io/ably/lib/liveobjects/value/LiveMapValue.java rename to lib/src/main/java/io/ably/pubsub/liveobjects/value/LiveMapValue.java index 406e48d02..0c35431b1 100644 --- a/lib/src/main/java/io/ably/lib/liveobjects/value/LiveMapValue.java +++ b/lib/src/main/java/io/ably/pubsub/liveobjects/value/LiveMapValue.java @@ -1,4 +1,4 @@ -package io.ably.lib.liveobjects.value; +package io.ably.pubsub.liveobjects.value; import com.google.gson.JsonArray; import com.google.gson.JsonObject; diff --git a/lib/src/main/java/io/ably/lib/liveobjects/value/package-info.java b/lib/src/main/java/io/ably/pubsub/liveobjects/value/package-info.java similarity index 67% rename from lib/src/main/java/io/ably/lib/liveobjects/value/package-info.java rename to lib/src/main/java/io/ably/pubsub/liveobjects/value/package-info.java index 6a4e798ec..69fadb23c 100644 --- a/lib/src/main/java/io/ably/lib/liveobjects/value/package-info.java +++ b/lib/src/main/java/io/ably/pubsub/liveobjects/value/package-info.java @@ -1,9 +1,9 @@ /** * Write-side value types for LiveObjects mutations. - * {@link io.ably.lib.liveobjects.value.LiveMapValue} is the union of values + * {@link io.ably.pubsub.liveobjects.value.LiveMapValue} is the union of values * assignable to a {@code LiveMap} key; - * {@link io.ably.lib.liveobjects.value.LiveMap} and - * {@link io.ably.lib.liveobjects.value.LiveCounter} are immutable initial-value + * {@link io.ably.pubsub.liveobjects.value.LiveMap} and + * {@link io.ably.pubsub.liveobjects.value.LiveCounter} are immutable initial-value * holders describing new objects to be created by a mutation; they expose only * the static {@code create} factories (RTLMV3 / RTLCV3), which delegate to the * LiveObjects implementation extending these abstract classes. Their internal @@ -13,4 +13,4 @@ *

Spec: RTLM20 / RTPO15a2 / RTINS12a2 (value union); RTLMV3 / RTLCV3 * (new-object value types) */ -package io.ably.lib.liveobjects.value; +package io.ably.pubsub.liveobjects.value; diff --git a/lib/src/main/java/io/ably/lib/push/PushBase.java b/lib/src/main/java/io/ably/pubsub/push/PushBase.java similarity index 91% rename from lib/src/main/java/io/ably/lib/push/PushBase.java rename to lib/src/main/java/io/ably/pubsub/push/PushBase.java index d175e0290..421959284 100644 --- a/lib/src/main/java/io/ably/lib/push/PushBase.java +++ b/lib/src/main/java/io/ably/pubsub/push/PushBase.java @@ -1,24 +1,24 @@ -package io.ably.lib.push; +package io.ably.pubsub.push; import com.google.gson.JsonElement; import com.google.gson.JsonObject; -import io.ably.lib.http.BasePaginatedQuery; -import io.ably.lib.http.Http; -import io.ably.lib.http.HttpCore; -import io.ably.lib.http.HttpScheduler; -import io.ably.lib.http.HttpUtils; -import io.ably.lib.realtime.CompletionListener; -import io.ably.lib.rest.AblyBase; -import io.ably.lib.rest.DeviceDetails; -import io.ably.lib.types.AblyException; -import io.ably.lib.types.AsyncPaginatedResult; -import io.ably.lib.types.Callback; -import io.ably.lib.types.PaginatedResult; -import io.ably.lib.types.Param; -import io.ably.lib.util.Log; -import io.ably.lib.util.ParamsUtils; -import io.ably.lib.util.Serialisation; -import io.ably.lib.util.StringUtils; +import io.ably.pubsub.http.BasePaginatedQuery; +import io.ably.pubsub.http.HttpRequester; +import io.ably.pubsub.http.HttpCore; +import io.ably.pubsub.http.HttpScheduler; +import io.ably.pubsub.http.HttpUtils; +import io.ably.pubsub.realtime.CompletionListener; +import io.ably.pubsub.http.PubSubBase; +import io.ably.pubsub.http.DeviceDetails; +import io.ably.pubsub.types.AblyException; +import io.ably.pubsub.types.AsyncPaginatedResult; +import io.ably.pubsub.types.Callback; +import io.ably.pubsub.types.PaginatedResult; +import io.ably.pubsub.types.Param; +import io.ably.pubsub.util.Log; +import io.ably.pubsub.util.ParamsUtils; +import io.ably.pubsub.util.Serialisation; +import io.ably.pubsub.util.StringUtils; import java.util.Arrays; import java.util.Map; @@ -27,7 +27,7 @@ * Enables a device to be registered and deregistered from receiving push notifications. */ public class PushBase { - public PushBase(AblyBase rest) { + public PushBase(PubSubBase rest) { this.rest = rest; this.admin = new Admin(rest); } @@ -48,7 +48,7 @@ public static class Admin { */ public final ChannelSubscriptions channelSubscriptions; - Admin(AblyBase rest) { + Admin(PubSubBase rest) { this.rest = rest; this.deviceRegistrations = new DeviceRegistrations(rest); this.channelSubscriptions = new ChannelSubscriptions(rest); @@ -83,9 +83,9 @@ public void publishAsync(Param[] recipient, JsonObject payload, final Completion publishImpl(recipient, payload).async(new CompletionListener.ToCallback<>(listener)); } - private Http.Request publishImpl(final Param[] recipient, final JsonObject payload) { + private HttpRequester.Request publishImpl(final Param[] recipient, final JsonObject payload) { Log.v(TAG, "publishImpl(): recipient=" + Arrays.toString(recipient) + ", payload=" + payload); - return rest.http.request(new Http.Execute() { + return rest.http.request(new HttpRequester.Execute() { @Override public void execute(HttpScheduler http, Callback callback) throws AblyException { if (recipient == null || recipient.length == 0) { @@ -112,7 +112,7 @@ public void execute(HttpScheduler http, Callback callback) throws AblyExce }); } - private final AblyBase rest; + private final PubSubBase rest; } /** @@ -148,10 +148,10 @@ public void saveAsync(DeviceDetails device, final Callback callba saveImpl(device).async(callback); } - protected Http.Request saveImpl(final DeviceDetails device) { + protected HttpRequester.Request saveImpl(final DeviceDetails device) { Log.v(TAG, "saveImpl(): device=" + device); final HttpCore.RequestBody body = HttpUtils.requestBodyFromGson(device.toJsonObject(), rest.options.useBinaryProtocol); - return rest.http.request(new Http.Execute() { + return rest.http.request(new HttpRequester.Execute() { @Override public void execute(HttpScheduler http, Callback callback) { Param[] params = ParamsUtils.enrichParams(null, rest.options); @@ -185,9 +185,9 @@ public void getAsync(String deviceId, final Callback callback) { getImpl(deviceId).async(callback); } - protected Http.Request getImpl(final String deviceId) { + protected HttpRequester.Request getImpl(final String deviceId) { Log.v(TAG, "getImpl(): deviceId=" + deviceId); - return rest.http.request(new Http.Execute() { + return rest.http.request(new HttpRequester.Execute() { @Override public void execute(HttpScheduler http, Callback callback) throws AblyException { Param[] params = ParamsUtils.enrichParams(null, rest.options); @@ -278,9 +278,9 @@ public void removeAsync(String deviceId, CompletionListener listener) { removeImpl(deviceId).async(new CompletionListener.ToCallback<>(listener)); } - protected Http.Request removeImpl(final String deviceId) { + protected HttpRequester.Request removeImpl(final String deviceId) { Log.v(TAG, "removeImpl(): deviceId=" + deviceId); - return rest.http.request(new Http.Execute() { + return rest.http.request(new HttpRequester.Execute() { @Override public void execute(HttpScheduler http, Callback callback) throws AblyException { Param[] params = ParamsUtils.enrichParams(null, rest.options); @@ -313,10 +313,10 @@ public void removeWhereAsync(Param[] params, CompletionListener listener) { removeWhereImpl(params).async(new CompletionListener.ToCallback<>(listener)); } - protected Http.Request removeWhereImpl(Param[] params) { + protected HttpRequester.Request removeWhereImpl(Param[] params) { Log.v(TAG, "removeWhereImpl(): params=" + Arrays.toString(params)); final Param[] finalParams = ParamsUtils.enrichParams(params, rest.options); - return rest.http.request(new Http.Execute() { + return rest.http.request(new HttpRequester.Execute() { @Override public void execute(HttpScheduler http, Callback callback) throws AblyException { http.del("/push/deviceRegistrations", HttpUtils.defaultAcceptHeaders(rest.options.useBinaryProtocol), finalParams, null, true, callback); @@ -324,11 +324,11 @@ public void execute(HttpScheduler http, Callback callback) throws AblyExce }); } - DeviceRegistrations(AblyBase rest) { + DeviceRegistrations(PubSubBase rest) { this.rest = rest; } - private final AblyBase rest; + private final PubSubBase rest; } /** @@ -364,10 +364,10 @@ public void saveAsync(ChannelSubscription subscription, final Callback saveImpl(final ChannelSubscription subscription) { + protected HttpRequester.Request saveImpl(final ChannelSubscription subscription) { Log.v(TAG, "saveImpl(): subscription=" + subscription); final HttpCore.RequestBody body = HttpUtils.requestBodyFromGson(subscription.toJsonObject(), rest.options.useBinaryProtocol); - return rest.http.request(new Http.Execute() { + return rest.http.request(new HttpRequester.Execute() { @Override public void execute(HttpScheduler http, Callback callback) throws AblyException { Param[] params = ParamsUtils.enrichParams(null, rest.options); @@ -438,7 +438,7 @@ public void removeAsync(ChannelSubscription subscription, CompletionListener lis removeImpl(subscription).async(new CompletionListener.ToCallback<>(listener)); } - protected Http.Request removeImpl(ChannelSubscription subscription) { + protected HttpRequester.Request removeImpl(ChannelSubscription subscription) { Log.v(TAG, "removeImpl(): subscription=" + subscription); Param[] params = new Param[] { new Param("channel", subscription.channel) }; if (subscription.deviceId != null) { @@ -479,12 +479,12 @@ public void removeWhereAsync(Param[] params, CompletionListener listener) { removeWhereImpl(params).async(new CompletionListener.ToCallback<>(listener)); } - protected Http.Request removeWhereImpl(Param[] params) { + protected HttpRequester.Request removeWhereImpl(Param[] params) { Log.v(TAG, "removeWhereImpl(): params=" + Arrays.toString(params)); String deviceId = HttpUtils.getParam(params, "deviceId"); final Param[] finalParams = ParamsUtils.enrichParams(params, rest.options); final Param[] finalHeaders = rest.push.pushRequestHeaders(deviceId); - return rest.http.request(new Http.Execute() { + return rest.http.request(new HttpRequester.Execute() { @Override public void execute(HttpScheduler http, Callback callback) throws AblyException { http.del("/push/channelSubscriptions", finalHeaders, finalParams, null, true, callback); @@ -528,11 +528,11 @@ protected BasePaginatedQuery.ResultRequest listChannelsImpl(Param[] para return new BasePaginatedQuery(rest.http, "/push/channels", rest.push.pushRequestHeaders(deviceId), params, StringUtils.httpBodyHandler).get(); } - ChannelSubscriptions(AblyBase rest) { + ChannelSubscriptions(PubSubBase rest) { this.rest = rest; } - private final AblyBase rest; + private final PubSubBase rest; } /** @@ -640,7 +640,7 @@ Param[] pushRequestHeaders(String deviceId) { return pushRequestHeaders(false); } - protected final AblyBase rest; + protected final PubSubBase rest; /** * A {@link PushBase.Admin} object. *

diff --git a/lib/src/main/java/io/ably/lib/push/Storage.java b/lib/src/main/java/io/ably/pubsub/push/Storage.java similarity index 97% rename from lib/src/main/java/io/ably/lib/push/Storage.java rename to lib/src/main/java/io/ably/pubsub/push/Storage.java index cb30dbd55..b8937e7cc 100644 --- a/lib/src/main/java/io/ably/lib/push/Storage.java +++ b/lib/src/main/java/io/ably/pubsub/push/Storage.java @@ -1,4 +1,4 @@ -package io.ably.lib.push; +package io.ably.pubsub.push; /** * Interface for an entity that supplies key value store diff --git a/lib/src/main/java/io/ably/lib/realtime/ChannelBase.java b/lib/src/main/java/io/ably/pubsub/realtime/ChannelBase.java similarity index 92% rename from lib/src/main/java/io/ably/lib/realtime/ChannelBase.java rename to lib/src/main/java/io/ably/pubsub/realtime/ChannelBase.java index 12feb0c61..e239fd711 100644 --- a/lib/src/main/java/io/ably/lib/realtime/ChannelBase.java +++ b/lib/src/main/java/io/ably/pubsub/realtime/ChannelBase.java @@ -1,4 +1,4 @@ -package io.ably.lib.realtime; +package io.ably.pubsub.realtime; import java.util.HashMap; import java.util.HashSet; @@ -9,51 +9,51 @@ import java.util.TimerTask; import java.util.concurrent.atomic.AtomicBoolean; -import io.ably.lib.http.BasePaginatedQuery; -import io.ably.lib.http.Http; -import io.ably.lib.http.HttpCore; -import io.ably.lib.http.HttpUtils; -import io.ably.lib.liveobjects.RealtimeObject; -import io.ably.lib.liveobjects.LiveObjectsPlugin; -import io.ably.lib.rest.MessageEditsMixin; -import io.ably.lib.rest.RestAnnotations; -import io.ably.lib.transport.ConnectionManager; -import io.ably.lib.transport.ConnectionManager.QueuedMessage; -import io.ably.lib.transport.Defaults; -import io.ably.lib.types.AblyException; -import io.ably.lib.types.AsyncPaginatedResult; -import io.ably.lib.types.Callback; -import io.ably.lib.types.ChannelMode; -import io.ably.lib.types.ChannelOptions; -import io.ably.lib.types.ChannelProperties; -import io.ably.lib.types.DecodingContext; -import io.ably.lib.types.DeltaExtras; -import io.ably.lib.types.ErrorInfo; -import io.ably.lib.types.Message; -import io.ably.lib.types.MessageAction; -import io.ably.lib.types.MessageAnnotations; -import io.ably.lib.types.MessageDecodeException; -import io.ably.lib.types.MessageOperation; -import io.ably.lib.types.MessageSerializer; -import io.ably.lib.types.MessageVersion; -import io.ably.lib.types.PaginatedResult; -import io.ably.lib.types.Param; -import io.ably.lib.types.PresenceMessage; -import io.ably.lib.types.ProtocolMessage; -import io.ably.lib.types.ProtocolMessage.Action; -import io.ably.lib.types.ProtocolMessage.Flag; -import io.ably.lib.types.PublishResult; -import io.ably.lib.types.Summary; -import io.ably.lib.types.UpdateDeleteResult; -import io.ably.lib.util.Clock; -import io.ably.lib.util.CollectionUtils; -import io.ably.lib.util.EventEmitter; -import io.ably.lib.util.Listeners; -import io.ably.lib.util.Log; -import io.ably.lib.util.AblyTimer; -import io.ably.lib.util.ReconnectionStrategy; -import io.ably.lib.util.StringUtils; -import io.ably.lib.util.SystemClock; +import io.ably.pubsub.http.BasePaginatedQuery; +import io.ably.pubsub.http.HttpRequester; +import io.ably.pubsub.http.HttpCore; +import io.ably.pubsub.http.HttpUtils; +import io.ably.pubsub.liveobjects.RealtimeObject; +import io.ably.pubsub.liveobjects.LiveObjectsPlugin; +import io.ably.pubsub.http.MessageEditsMixin; +import io.ably.pubsub.http.HttpAnnotations; +import io.ably.pubsub.transport.ConnectionManager; +import io.ably.pubsub.transport.ConnectionManager.QueuedMessage; +import io.ably.pubsub.transport.Defaults; +import io.ably.pubsub.types.AblyException; +import io.ably.pubsub.types.AsyncPaginatedResult; +import io.ably.pubsub.types.Callback; +import io.ably.pubsub.types.ChannelMode; +import io.ably.pubsub.types.ChannelOptions; +import io.ably.pubsub.types.ChannelProperties; +import io.ably.pubsub.types.DecodingContext; +import io.ably.pubsub.types.DeltaExtras; +import io.ably.pubsub.types.ErrorInfo; +import io.ably.pubsub.types.Message; +import io.ably.pubsub.types.MessageAction; +import io.ably.pubsub.types.MessageAnnotations; +import io.ably.pubsub.types.MessageDecodeException; +import io.ably.pubsub.types.MessageOperation; +import io.ably.pubsub.types.MessageSerializer; +import io.ably.pubsub.types.MessageVersion; +import io.ably.pubsub.types.PaginatedResult; +import io.ably.pubsub.types.Param; +import io.ably.pubsub.types.PresenceMessage; +import io.ably.pubsub.types.ProtocolMessage; +import io.ably.pubsub.types.ProtocolMessage.Action; +import io.ably.pubsub.types.ProtocolMessage.Flag; +import io.ably.pubsub.types.PublishResult; +import io.ably.pubsub.types.Summary; +import io.ably.pubsub.types.UpdateDeleteResult; +import io.ably.pubsub.util.Clock; +import io.ably.pubsub.util.CollectionUtils; +import io.ably.pubsub.util.EventEmitter; +import io.ably.pubsub.util.Listeners; +import io.ably.pubsub.util.Log; +import io.ably.pubsub.util.AblyTimer; +import io.ably.pubsub.util.ReconnectionStrategy; +import io.ably.pubsub.util.StringUtils; +import io.ably.pubsub.util.SystemClock; import org.jetbrains.annotations.Blocking; import org.jetbrains.annotations.NonBlocking; import org.jetbrains.annotations.Nullable; @@ -425,11 +425,6 @@ private static void callCompletionListenerSuccess(CompletionListener listener) { } } - @Deprecated - public void sync() throws AblyException { - Log.w(TAG, "sync() method is intended only for internal testing purpose as per RTP19"); - } - private static void callCompletionListenerError(CompletionListener listener, ErrorInfo err) { if(listener != null) { try { @@ -777,9 +772,9 @@ public synchronized void unsubscribe() { /** *

- * Checks if {@link io.ably.lib.types.ChannelOptions#attachOnSubscribe} is true. + * Checks if {@link io.ably.pubsub.types.ChannelOptions#attachOnSubscribe} is true. *

- * Defaults to {@code true} when {@link io.ably.lib.realtime.ChannelBase#options} is null. + * Defaults to {@code true} when {@link io.ably.pubsub.realtime.ChannelBase#options} is null. *

Spec: TB4, RTL7g, RTL7h, RTP6d, RTP6e

*/ protected boolean attachOnSubscribeEnabled() { @@ -985,7 +980,7 @@ public void onError(ErrorInfo reason) { private MessageMulticaster listeners = new MessageMulticaster(); private HashMap eventListeners = new HashMap(); - private static class MessageMulticaster extends io.ably.lib.util.Multicaster implements MessageListener { + private static class MessageMulticaster extends io.ably.pubsub.util.Multicaster implements MessageListener { @Override public void onMessage(Message message) { for (final MessageListener member : getMembers()) @@ -1061,28 +1056,6 @@ public void publish(Message[] messages) throws AblyException { publish(messages, (Callback) null); } - /** - * Publishes a single message to the channel with the given event name and payload. - * When publish is called with this client library, it won't attempt to implicitly attach to the channel, - * so long as transient publishing is available in the library. - * Otherwise, the client will implicitly attach. - *

- * Spec: RTL6i - * @param name the event name - * @param data the message payload - * @param listener A listener may optionally be passed in to this call to be notified of success or failure of the operation. - *

- * This listener is invoked on a background thread. - * @throws AblyException - * @deprecated Use {@link #publish(String, Object, Callback)} instead. - */ - @Deprecated - @NonBlocking - public void publish(String name, Object data, CompletionListener listener) throws AblyException { - Log.v(TAG, "publish(String, Object); channel = " + this.name + "; event = " + name); - publish(new Message[] {new Message(name, data)}, listener); - } - /** * Publishes a single message to the channel with the given event name and payload. * When publish is called with this client library, it won't attempt to implicitly attach to the channel, @@ -1104,25 +1077,6 @@ public void publish(String name, Object data, Callback callback) publish(new Message[] {new Message(name, data)}, callback); } - /** - * Publishes a message to the channel. - * When publish is called with this client library, it won't attempt to implicitly attach to the channel. - *

- * Spec: RTL6i - * @param message A {@link Message} object. - * @param listener A listener may optionally be passed in to this call to be notified of success or failure of the operation. - *

- * This listener is invoked on a background thread. - * @throws AblyException - * @deprecated Use {@link #publish(Message, Callback)} instead. - */ - @Deprecated - @NonBlocking - public void publish(Message message, CompletionListener listener) throws AblyException { - Log.v(TAG, "publish(Message); channel = " + this.name + "; event = " + message.name); - publish(new Message[] {message}, listener); - } - /** * Publishes a message to the channel. * When publish is called with this client library, it won't attempt to implicitly attach to the channel. @@ -1141,24 +1095,6 @@ public void publish(Message message, Callback callback) throws Ab publish(new Message[] {message}, callback); } - /** - * Publishes an array of messages to the channel. - * When publish is called with this client library, it won't attempt to implicitly attach to the channel. - *

- * Spec: RTL6i - * @param messages An array of {@link Message} objects. - * @param listener A listener may optionally be passed in to this call to be notified of success or failure of the operation. - *

- * This listener is invoked on a background thread. - * @throws AblyException - * @deprecated Use {@link #publish(Message[], Callback)} instead. - */ - @Deprecated - @NonBlocking - public synchronized void publish(Message[] messages, CompletionListener listener) throws AblyException { - publish(messages, Listeners.fromCompletionListener(listener)); - } - @NonBlocking public synchronized void publish(Message[] messages, Callback listener) throws AblyException { Log.v(TAG, "publish(Message[]); channel = " + this.name); @@ -1543,7 +1479,7 @@ public PaginatedResult history(Param[] params) throws AblyException { return historyImpl(ably.http, params).sync(); } - PaginatedResult history(Http http, Param[] params) throws AblyException { + PaginatedResult history(HttpRequester http, Param[] params) throws AblyException { return historyImpl(http, params).sync(); } @@ -1576,11 +1512,11 @@ public void historyAsync(Param[] params, Callback> historyAsync(ably.http, params, callback); } - void historyAsync(Http http, Param[] params, Callback> callback) { + void historyAsync(HttpRequester http, Param[] params, Callback> callback) { historyImpl(http, params).async(callback); } - private BasePaginatedQuery.ResultRequest historyImpl(Http http, Param[] params) { + private BasePaginatedQuery.ResultRequest historyImpl(HttpRequester http, Param[] params) { try { params = replacePlaceholderParams((Channel) this, params); } catch (AblyException e) { @@ -1674,7 +1610,7 @@ else if(stateChange.current.equals(failureState)) { } } - ChannelBase(AblyRealtime ably, String name, ChannelOptions options, @Nullable LiveObjectsPlugin liveObjectsPlugin) throws AblyException { + ChannelBase(PubSubRealtimeClient ably, String name, ChannelOptions options, @Nullable LiveObjectsPlugin liveObjectsPlugin) throws AblyException { Log.v(TAG, "RealtimeChannel(); channel = " + name); this.ably = ably; this.clock = SystemClock.clockFrom(ably.options); @@ -1693,7 +1629,7 @@ else if(stateChange.current.equals(failureState)) { } this.annotations = new RealtimeAnnotations( this, - new RestAnnotations(name, ably.http, ably.options, options) + new HttpAnnotations(name, ably.http, ably.options, options) ); this.messageEditsMixin = new MessageEditsMixin(basePath, ably.options, options, ably.auth); } @@ -1803,7 +1739,7 @@ public void sendProtocolMessage(ProtocolMessage protocolMessage, CompletionListe } private static final String TAG = Channel.class.getName(); - final AblyRealtime ably; + final PubSubRealtimeClient ably; final Clock clock; final String basePath; ChannelOptions options; diff --git a/lib/src/main/java/io/ably/lib/realtime/ChannelEvent.java b/lib/src/main/java/io/ably/pubsub/realtime/ChannelEvent.java similarity index 92% rename from lib/src/main/java/io/ably/lib/realtime/ChannelEvent.java rename to lib/src/main/java/io/ably/pubsub/realtime/ChannelEvent.java index 4cce47e1d..c31f37230 100644 --- a/lib/src/main/java/io/ably/lib/realtime/ChannelEvent.java +++ b/lib/src/main/java/io/ably/pubsub/realtime/ChannelEvent.java @@ -1,4 +1,4 @@ -package io.ably.lib.realtime; +package io.ably.pubsub.realtime; /** * Describes the events emitted by a {@link Channel} object. diff --git a/lib/src/main/java/io/ably/lib/realtime/ChannelState.java b/lib/src/main/java/io/ably/pubsub/realtime/ChannelState.java similarity index 98% rename from lib/src/main/java/io/ably/lib/realtime/ChannelState.java rename to lib/src/main/java/io/ably/pubsub/realtime/ChannelState.java index 202659e12..a13e04a5a 100644 --- a/lib/src/main/java/io/ably/lib/realtime/ChannelState.java +++ b/lib/src/main/java/io/ably/pubsub/realtime/ChannelState.java @@ -1,4 +1,4 @@ -package io.ably.lib.realtime; +package io.ably.pubsub.realtime; /** * Describes the possible states of a {@link Channel} object. diff --git a/lib/src/main/java/io/ably/lib/realtime/ChannelStateListener.java b/lib/src/main/java/io/ably/pubsub/realtime/ChannelStateListener.java similarity index 94% rename from lib/src/main/java/io/ably/lib/realtime/ChannelStateListener.java rename to lib/src/main/java/io/ably/pubsub/realtime/ChannelStateListener.java index 5a84d3f69..7e13b51c9 100644 --- a/lib/src/main/java/io/ably/lib/realtime/ChannelStateListener.java +++ b/lib/src/main/java/io/ably/pubsub/realtime/ChannelStateListener.java @@ -1,6 +1,6 @@ -package io.ably.lib.realtime; +package io.ably.pubsub.realtime; -import io.ably.lib.types.ErrorInfo; +import io.ably.pubsub.types.ErrorInfo; import org.jetbrains.annotations.NotNull; /** @@ -83,7 +83,7 @@ static ChannelStateChange createUpdateEvent(ErrorInfo reason, boolean resumed) { } } - class Multicaster extends io.ably.lib.util.Multicaster implements ChannelStateListener { + class Multicaster extends io.ably.pubsub.util.Multicaster implements ChannelStateListener { @Override public void onChannelStateChanged(ChannelStateChange stateChange) { for (final ChannelStateListener member : getMembers()) diff --git a/lib/src/main/java/io/ably/lib/realtime/CompletionListener.java b/lib/src/main/java/io/ably/pubsub/realtime/CompletionListener.java similarity index 89% rename from lib/src/main/java/io/ably/lib/realtime/CompletionListener.java rename to lib/src/main/java/io/ably/pubsub/realtime/CompletionListener.java index c2c9c8eb5..808fc6eb7 100644 --- a/lib/src/main/java/io/ably/lib/realtime/CompletionListener.java +++ b/lib/src/main/java/io/ably/pubsub/realtime/CompletionListener.java @@ -1,7 +1,7 @@ -package io.ably.lib.realtime; +package io.ably.pubsub.realtime; -import io.ably.lib.types.Callback; -import io.ably.lib.types.ErrorInfo; +import io.ably.pubsub.types.Callback; +import io.ably.pubsub.types.ErrorInfo; /** * An interface allowing a client to be notified of the outcome @@ -23,7 +23,7 @@ public interface CompletionListener { * A Multicaster instance is used in the Ably library to manage a list * of client listeners against certain operations. */ - class Multicaster extends io.ably.lib.util.Multicaster implements CompletionListener { + class Multicaster extends io.ably.pubsub.util.Multicaster implements CompletionListener { public Multicaster(CompletionListener... members) { super(members); } @Override diff --git a/lib/src/main/java/io/ably/lib/realtime/Connection.java b/lib/src/main/java/io/ably/pubsub/realtime/Connection.java similarity index 69% rename from lib/src/main/java/io/ably/lib/realtime/Connection.java rename to lib/src/main/java/io/ably/pubsub/realtime/Connection.java index dde9238d0..da614ca6d 100644 --- a/lib/src/main/java/io/ably/lib/realtime/Connection.java +++ b/lib/src/main/java/io/ably/pubsub/realtime/Connection.java @@ -1,14 +1,14 @@ -package io.ably.lib.realtime; - -import io.ably.lib.liveobjects.LiveObjectsPlugin; -import io.ably.lib.realtime.ConnectionStateListener.ConnectionStateChange; -import io.ably.lib.transport.ConnectionManager; -import io.ably.lib.types.AblyException; -import io.ably.lib.types.ErrorInfo; -import io.ably.lib.types.RecoveryKeyContext; -import io.ably.lib.util.EventEmitter; -import io.ably.lib.util.Log; -import io.ably.lib.util.PlatformAgentProvider; +package io.ably.pubsub.realtime; + +import io.ably.pubsub.liveobjects.LiveObjectsPlugin; +import io.ably.pubsub.realtime.ConnectionStateListener.ConnectionStateChange; +import io.ably.pubsub.transport.ConnectionManager; +import io.ably.pubsub.types.AblyException; +import io.ably.pubsub.types.ErrorInfo; +import io.ably.pubsub.types.RecoveryKeyContext; +import io.ably.pubsub.util.EventEmitter; +import io.ably.pubsub.util.Log; +import io.ably.pubsub.util.PlatformAgentProvider; /** * Enables the management of a connection to Ably. @@ -34,8 +34,8 @@ public class Connection extends EventEmitterpublishing over REST on behalf of a realtime client docs @@ -45,17 +45,6 @@ public class Connection extends EventEmitterconnection state recover options - * for more information. - *

- * Spec: RTN16m - * @deprecated use createRecoveryKey method instead. - */ - @Deprecated - public String recoveryKey; - /** * createRecoveryKey is a method that returns a json string which incorporates the @connectionKey@, the * current @msgSerial@, and a collection of pairs of channel @name@ and current @channelSerial@ for every @@ -84,7 +73,7 @@ public String createRecoveryKey() { public String id; /** - * Explicitly calling connect() is unnecessary unless the autoConnect attribute of the {@link io.ably.lib.types.ClientOptions} + * Explicitly calling connect() is unnecessary unless the autoConnect attribute of the {@link io.ably.pubsub.types.ClientOptions} * object is false. * Unless already connected or connecting, this method causes the connection to open, * entering the {@link ConnectionState#connecting} state. @@ -115,7 +104,6 @@ public void ping(CompletionListener listener) { */ public void close() { key = null; - recoveryKey = null; connectionManager.close(); } @@ -123,7 +111,7 @@ public void close() { * internal *****************/ - Connection(AblyRealtime ably, ConnectionManager.Channels channels, PlatformAgentProvider platformAgentProvider, LiveObjectsPlugin liveObjectsPlugin) throws AblyException { + Connection(PubSubRealtimeClient ably, ConnectionManager.Channels channels, PlatformAgentProvider platformAgentProvider, LiveObjectsPlugin liveObjectsPlugin) throws AblyException { this.ably = ably; this.state = ConnectionState.initialized; this.connectionManager = new ConnectionManager(ably, this, channels, platformAgentProvider, liveObjectsPlugin); @@ -132,7 +120,7 @@ public void close() { public void onConnectionStateChange(ConnectionStateChange stateChange) { state = stateChange.current; reason = stateChange.reason; - emit(state, stateChange); + emit(state.getConnectionEvent(), stateChange); } @Override @@ -149,22 +137,7 @@ public void emitUpdate(ErrorInfo errorInfo) { emit(ConnectionEvent.update, ConnectionStateListener.ConnectionStateChange.createUpdateEvent(errorInfo)); } - @Deprecated - public void emit(ConnectionState state, ConnectionStateChange stateChange) { - super.emit(state.getConnectionEvent(), stateChange); - } - - @Deprecated - public void on(ConnectionState state, ConnectionStateListener listener) { - super.on(state.getConnectionEvent(), listener); - } - - @Deprecated - public void once(ConnectionState state, ConnectionStateListener listener) { - super.once(state.getConnectionEvent(), listener); - } - private static final String TAG = Connection.class.getName(); - final AblyRealtime ably; + final PubSubRealtimeClient ably; public final ConnectionManager connectionManager; } diff --git a/lib/src/main/java/io/ably/lib/realtime/ConnectionEvent.java b/lib/src/main/java/io/ably/pubsub/realtime/ConnectionEvent.java similarity index 93% rename from lib/src/main/java/io/ably/lib/realtime/ConnectionEvent.java rename to lib/src/main/java/io/ably/pubsub/realtime/ConnectionEvent.java index dc223150c..e7430b4ae 100644 --- a/lib/src/main/java/io/ably/lib/realtime/ConnectionEvent.java +++ b/lib/src/main/java/io/ably/pubsub/realtime/ConnectionEvent.java @@ -1,4 +1,4 @@ -package io.ably.lib.realtime; +package io.ably.pubsub.realtime; /** * Describes the events emitted by a {@link Connection} object. An event is either an UPDATE or a {@link ConnectionState}. diff --git a/lib/src/main/java/io/ably/lib/realtime/ConnectionState.java b/lib/src/main/java/io/ably/pubsub/realtime/ConnectionState.java similarity index 99% rename from lib/src/main/java/io/ably/lib/realtime/ConnectionState.java rename to lib/src/main/java/io/ably/pubsub/realtime/ConnectionState.java index 0f997f8b0..0b613805f 100644 --- a/lib/src/main/java/io/ably/lib/realtime/ConnectionState.java +++ b/lib/src/main/java/io/ably/pubsub/realtime/ConnectionState.java @@ -1,4 +1,4 @@ -package io.ably.lib.realtime; +package io.ably.pubsub.realtime; /** * Describes the realtime {@link Connection} object states. diff --git a/lib/src/main/java/io/ably/lib/realtime/ConnectionStateListener.java b/lib/src/main/java/io/ably/pubsub/realtime/ConnectionStateListener.java similarity index 94% rename from lib/src/main/java/io/ably/lib/realtime/ConnectionStateListener.java rename to lib/src/main/java/io/ably/pubsub/realtime/ConnectionStateListener.java index 5b57f5871..8b25668a6 100644 --- a/lib/src/main/java/io/ably/lib/realtime/ConnectionStateListener.java +++ b/lib/src/main/java/io/ably/pubsub/realtime/ConnectionStateListener.java @@ -1,6 +1,6 @@ -package io.ably.lib.realtime; +package io.ably.pubsub.realtime; -import io.ably.lib.types.ErrorInfo; +import io.ably.pubsub.types.ErrorInfo; /** * An interface whereby a client may be notified of state changes for a connection. @@ -71,7 +71,7 @@ public static ConnectionStateChange createUpdateEvent(ErrorInfo reason) { } } - class Multicaster extends io.ably.lib.util.Multicaster implements ConnectionStateListener { + class Multicaster extends io.ably.pubsub.util.Multicaster implements ConnectionStateListener { @Override public void onConnectionStateChanged(ConnectionStateChange state) { for (final ConnectionStateListener member : getMembers()) diff --git a/lib/src/main/java/io/ably/lib/realtime/Presence.java b/lib/src/main/java/io/ably/pubsub/realtime/Presence.java similarity index 97% rename from lib/src/main/java/io/ably/lib/realtime/Presence.java rename to lib/src/main/java/io/ably/pubsub/realtime/Presence.java index 98b7a1ffe..8f9a86d90 100644 --- a/lib/src/main/java/io/ably/lib/realtime/Presence.java +++ b/lib/src/main/java/io/ably/pubsub/realtime/Presence.java @@ -1,24 +1,24 @@ -package io.ably.lib.realtime; - -import io.ably.lib.http.BasePaginatedQuery; -import io.ably.lib.http.Http; -import io.ably.lib.http.HttpCore; -import io.ably.lib.http.HttpUtils; -import io.ably.lib.transport.ConnectionManager; -import io.ably.lib.types.AblyException; -import io.ably.lib.types.AsyncPaginatedResult; -import io.ably.lib.types.Callback; -import io.ably.lib.types.ErrorInfo; -import io.ably.lib.types.MessageDecodeException; -import io.ably.lib.types.PaginatedResult; -import io.ably.lib.types.Param; -import io.ably.lib.types.PresenceMessage; -import io.ably.lib.types.PresenceSerializer; -import io.ably.lib.types.ProtocolMessage; -import io.ably.lib.types.PublishResult; -import io.ably.lib.util.Listeners; -import io.ably.lib.util.Log; -import io.ably.lib.util.StringUtils; +package io.ably.pubsub.realtime; + +import io.ably.pubsub.http.BasePaginatedQuery; +import io.ably.pubsub.http.HttpRequester; +import io.ably.pubsub.http.HttpCore; +import io.ably.pubsub.http.HttpUtils; +import io.ably.pubsub.transport.ConnectionManager; +import io.ably.pubsub.types.AblyException; +import io.ably.pubsub.types.AsyncPaginatedResult; +import io.ably.pubsub.types.Callback; +import io.ably.pubsub.types.ErrorInfo; +import io.ably.pubsub.types.MessageDecodeException; +import io.ably.pubsub.types.PaginatedResult; +import io.ably.pubsub.types.Param; +import io.ably.pubsub.types.PresenceMessage; +import io.ably.pubsub.types.PresenceSerializer; +import io.ably.pubsub.types.ProtocolMessage; +import io.ably.pubsub.types.PublishResult; +import io.ably.pubsub.util.Listeners; +import io.ably.pubsub.util.Log; +import io.ably.pubsub.util.StringUtils; import java.util.ArrayList; import java.util.Collection; @@ -49,7 +49,7 @@ public class Presence { /** * Retrieves the current members present on the channel and the metadata for each member, - * such as their {@link io.ably.lib.types.PresenceMessage.Action} and ID. + * such as their {@link io.ably.pubsub.types.PresenceMessage.Action} and ID. * Returns an array of {@link PresenceMessage} objects. *

* Spec: RTP11 @@ -85,7 +85,7 @@ public synchronized PresenceMessage[] get(Param... params) throws AblyException /** * Retrieves the current members present on the channel and the metadata for each member, - * such as their {@link io.ably.lib.types.PresenceMessage.Action} and ID. + * such as their {@link io.ably.pubsub.types.PresenceMessage.Action} and ID. * Returns an array of {@link PresenceMessage} objects. *

* Spec: RTP11 @@ -104,7 +104,7 @@ public synchronized PresenceMessage[] get(boolean wait) throws AblyException { /** * Retrieves the current members present on the channel and the metadata for each member, - * such as their {@link io.ably.lib.types.PresenceMessage.Action} and ID. + * such as their {@link io.ably.pubsub.types.PresenceMessage.Action} and ID. * Returns an array of {@link PresenceMessage} objects. *

* Spec: RTP11 @@ -434,7 +434,7 @@ private void broadcastPresence(List messages) { private final Multicaster listeners = new Multicaster(); private final EnumMap eventListeners = new EnumMap<>(PresenceMessage.Action.class); - private static class Multicaster extends io.ably.lib.util.Multicaster implements PresenceListener { + private static class Multicaster extends io.ably.pubsub.util.Multicaster implements PresenceListener { @Override public void onPresenceMessage(PresenceMessage message) { for (final PresenceListener member : getMembers()) @@ -740,7 +740,7 @@ public void leaveClient(String clientId, Object data, CompletionListener listene public void updatePresence(PresenceMessage msg, CompletionListener listener) throws AblyException { Log.v(TAG, "updatePresence(); channel = " + channel.name); - AblyRealtime ably = channel.ably; + PubSubRealtimeClient ably = channel.ably; boolean connected = (ably.connection.state == ConnectionState.connected); try { ably.auth.checkClientId(msg, false, connected); @@ -802,7 +802,7 @@ public PaginatedResult history(Param[] params) throws AblyExcep return history(channel.ably.http, params); } - PaginatedResult history(Http http, Param[] params) throws AblyException { + PaginatedResult history(HttpRequester http, Param[] params) throws AblyException { return historyImpl(http, params).sync(); } @@ -833,18 +833,18 @@ public void historyAsync(Param[] params, Callback> callback) { + void historyAsync(HttpRequester http, Param[] params, Callback> callback) { historyImpl(http, params).async(callback); } - private BasePaginatedQuery.ResultRequest historyImpl(Http http, Param[] params) { + private BasePaginatedQuery.ResultRequest historyImpl(HttpRequester http, Param[] params) { try { params = Channel.replacePlaceholderParams(channel, params); } catch (AblyException e) { return new BasePaginatedQuery.ResultRequest.Failed(e); } - AblyRealtime ably = channel.ably; + PubSubRealtimeClient ably = channel.ably; HttpCore.BodyHandler bodyHandler = PresenceSerializer.getPresenceResponseHandler(channel.options); return new BasePaginatedQuery(http, channel.basePath + "/presence/history", HttpUtils.defaultAcceptHeaders(ably.options.useBinaryProtocol), params, bodyHandler).get(); } @@ -863,7 +863,7 @@ private static class QueuedPresence { private void sendQueuedMessages() { Log.v(TAG, "sendQueuedMessages()"); - AblyRealtime ably = channel.ably; + PubSubRealtimeClient ably = channel.ably; boolean queueMessages = ably.options.queueMessages; ConnectionManager connectionManager = ably.connection.connectionManager; int count = pendingPresence.size(); diff --git a/lib/src/main/java/io/ably/lib/realtime/AblyRealtime.java b/lib/src/main/java/io/ably/pubsub/realtime/PubSubRealtimeClient.java similarity index 87% rename from lib/src/main/java/io/ably/lib/realtime/AblyRealtime.java rename to lib/src/main/java/io/ably/pubsub/realtime/PubSubRealtimeClient.java index 553afa90a..b30b0e849 100644 --- a/lib/src/main/java/io/ably/lib/realtime/AblyRealtime.java +++ b/lib/src/main/java/io/ably/pubsub/realtime/PubSubRealtimeClient.java @@ -1,33 +1,33 @@ -package io.ably.lib.realtime; +package io.ably.pubsub.realtime; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; -import io.ably.lib.liveobjects.LiveObjectsPlugin; -import io.ably.lib.rest.AblyRest; -import io.ably.lib.rest.Auth; -import io.ably.lib.transport.ConnectionManager; -import io.ably.lib.types.AblyException; -import io.ably.lib.types.ChannelOptions; -import io.ably.lib.types.ClientOptions; -import io.ably.lib.types.ErrorInfo; -import io.ably.lib.types.ProtocolMessage; -import io.ably.lib.types.ReadOnlyMap; -import io.ably.lib.types.RecoveryKeyContext; -import io.ably.lib.util.InternalMap; -import io.ably.lib.util.Log; -import io.ably.lib.util.StringUtils; +import io.ably.pubsub.liveobjects.LiveObjectsPlugin; +import io.ably.pubsub.http.PubSubHttpClient; +import io.ably.pubsub.http.Auth; +import io.ably.pubsub.transport.ConnectionManager; +import io.ably.pubsub.types.AblyException; +import io.ably.pubsub.types.ChannelOptions; +import io.ably.pubsub.types.ClientOptions; +import io.ably.pubsub.types.ErrorInfo; +import io.ably.pubsub.types.ProtocolMessage; +import io.ably.pubsub.types.ReadOnlyMap; +import io.ably.pubsub.types.RecoveryKeyContext; +import io.ably.pubsub.util.InternalMap; +import io.ably.pubsub.util.Log; +import io.ably.pubsub.util.StringUtils; import org.jetbrains.annotations.Nullable; /** - * A client that extends the functionality of the {@link AblyRest} and provides additional realtime-specific features. + * A client that extends the functionality of the {@link PubSubHttpClient} and provides additional realtime-specific features. * * This class implements {@link AutoCloseable} so you can use it in * try-with-resources constructs and have the JDK close it for you. */ -public class AblyRealtime extends AblyRest { +public class PubSubRealtimeClient extends PubSubHttpClient { /** * The {@link Connection} object for this instance. *

@@ -51,24 +51,17 @@ public class AblyRealtime extends AblyRest { private final LiveObjectsPlugin liveObjectsPlugin; /** - * Constructs a Realtime client object using an Ably API key or token string. + * Constructs a PubSubRealtimeClient object using an Ably {@link ClientOptions} object. *

- * Spec: RSC1 - * @param key The Ably API key or token string used to validate the client. - * @throws AblyException - */ - public AblyRealtime(String key) throws AblyException { - this(new ClientOptions(key)); - } - - /** - * Constructs a RealtimeClient object using an Ably {@link ClientOptions} object. + * Not public: a client is obtained from the builders of the {@code io.ably.pubsub:device} or + * {@code io.ably.pubsub:server} artifact, which name the side of the connection your code + * runs on. {@link RealtimeClientFactory} is the seam those builders construct through. *

* Spec: RSC1 * @param options A {@link ClientOptions} object. * @throws AblyException */ - public AblyRealtime(ClientOptions options) throws AblyException { + protected PubSubRealtimeClient(ClientOptions options) throws AblyException { super(options); final InternalChannels channels = new InternalChannels(); this.channels = channels; @@ -205,7 +198,7 @@ public Channel get(final String channelName, final ChannelOptions channelOptions // We're not using computeIfAbsent because that requires Java 1.8. // Hence there's the slight inefficiency of creating newChannel when it may not be // needed because there is an existingChannel. - final Channel newChannel = new Channel(AblyRealtime.this, channelName, channelOptions, liveObjectsPlugin); + final Channel newChannel = new Channel(PubSubRealtimeClient.this, channelName, channelOptions, liveObjectsPlugin); final Channel existingChannel = map.putIfAbsent(channelName, newChannel); if (existingChannel != null) { @@ -314,5 +307,5 @@ protected Map getChannelSerials() { * internal ********************/ - private static final String TAG = AblyRealtime.class.getName(); + private static final String TAG = PubSubRealtimeClient.class.getName(); } diff --git a/lib/src/main/java/io/ably/lib/realtime/RealtimeAnnotations.java b/lib/src/main/java/io/ably/pubsub/realtime/RealtimeAnnotations.java similarity index 94% rename from lib/src/main/java/io/ably/lib/realtime/RealtimeAnnotations.java rename to lib/src/main/java/io/ably/pubsub/realtime/RealtimeAnnotations.java index 2be2b36c2..51b77c7ef 100644 --- a/lib/src/main/java/io/ably/lib/realtime/RealtimeAnnotations.java +++ b/lib/src/main/java/io/ably/pubsub/realtime/RealtimeAnnotations.java @@ -1,19 +1,19 @@ -package io.ably.lib.realtime; - -import io.ably.lib.rest.RestAnnotations; -import io.ably.lib.types.AblyException; -import io.ably.lib.types.Annotation; -import io.ably.lib.types.AnnotationAction; -import io.ably.lib.types.AsyncPaginatedResult; -import io.ably.lib.types.Callback; -import io.ably.lib.types.ErrorInfo; -import io.ably.lib.types.Message; -import io.ably.lib.types.MessageDecodeException; -import io.ably.lib.types.PaginatedResult; -import io.ably.lib.types.Param; -import io.ably.lib.types.ProtocolMessage; -import io.ably.lib.util.Log; -import io.ably.lib.util.Multicaster; +package io.ably.pubsub.realtime; + +import io.ably.pubsub.http.HttpAnnotations; +import io.ably.pubsub.types.AblyException; +import io.ably.pubsub.types.Annotation; +import io.ably.pubsub.types.AnnotationAction; +import io.ably.pubsub.types.AsyncPaginatedResult; +import io.ably.pubsub.types.Callback; +import io.ably.pubsub.types.ErrorInfo; +import io.ably.pubsub.types.Message; +import io.ably.pubsub.types.MessageDecodeException; +import io.ably.pubsub.types.PaginatedResult; +import io.ably.pubsub.types.Param; +import io.ably.pubsub.types.ProtocolMessage; +import io.ably.pubsub.util.Log; +import io.ably.pubsub.util.Multicaster; import java.util.ArrayList; import java.util.HashMap; @@ -34,13 +34,13 @@ public class RealtimeAnnotations { private static final String TAG = RealtimeAnnotations.class.getName(); private final ChannelBase channel; - private final RestAnnotations restAnnotations; + private final HttpAnnotations httpAnnotations; private final AnnotationMulticaster listeners = new AnnotationMulticaster(); private final Map typeListeners = new HashMap<>(); - public RealtimeAnnotations(ChannelBase channel, RestAnnotations restAnnotations) { + public RealtimeAnnotations(ChannelBase channel, HttpAnnotations httpAnnotations) { this.channel = channel; - this.restAnnotations = restAnnotations; + this.httpAnnotations = httpAnnotations; } /** @@ -168,7 +168,7 @@ public void delete(Message message, Annotation annotation) throws AblyException * @throws AblyException if an error occurs during the retrieval process. */ public PaginatedResult get(String messageSerial, Param[] params) throws AblyException { - return restAnnotations.get(messageSerial, params); + return httpAnnotations.get(messageSerial, params); } /** @@ -189,7 +189,7 @@ public PaginatedResult get(Message message, Param[] params) throws A * @throws AblyException if an error occurs during the retrieval process */ public PaginatedResult get(String messageSerial) throws AblyException { - return restAnnotations.get(messageSerial, null); + return httpAnnotations.get(messageSerial, null); } /** @@ -210,7 +210,7 @@ public PaginatedResult get(Message message) throws AblyException { * @param callback a callback to handle the result asynchronously, providing an {@link AsyncPaginatedResult} containing the matching annotations. */ public void getAsync(String messageSerial, Param[] params, Callback> callback) throws AblyException { - restAnnotations.getAsync(messageSerial, params, callback); + httpAnnotations.getAsync(messageSerial, params, callback); } /** @@ -230,7 +230,7 @@ public void getAsync(Message message, Param[] params, Callback> callback) throws AblyException { - restAnnotations.getAsync(messageSerial, null, callback); + httpAnnotations.getAsync(messageSerial, null, callback); } /** diff --git a/lib/src/main/java/io/ably/pubsub/realtime/RealtimeClientFactory.java b/lib/src/main/java/io/ably/pubsub/realtime/RealtimeClientFactory.java new file mode 100644 index 000000000..8f794ada5 --- /dev/null +++ b/lib/src/main/java/io/ably/pubsub/realtime/RealtimeClientFactory.java @@ -0,0 +1,33 @@ +package io.ably.pubsub.realtime; + +import io.ably.pubsub.types.AblyException; +import io.ably.pubsub.types.ClientOptions; + +/** + * The seam through which a {@link PubSubRealtimeClient} is constructed, now that the client's own + * constructors are not public. + *

+ * It exists for the {@code io.ably.pubsub:device} and {@code io.ably.pubsub:server} door + * artifacts, whose builders are the supported way to obtain a client, and for this SDK's own + * tests. It sits in the client's package so that it can reach the non-public constructor. + *

+ * Application code should declare the side it runs on and use that artifact's builder instead: + * {@code io.ably.pubsub.device.PubSubDevice#clientBuilder()} on an end-user device, or + * {@code io.ably.pubsub.server.PubSubServer#realtimeClientBuilder()} on infrastructure you + * control. + */ +public final class RealtimeClientFactory { + private RealtimeClientFactory() {} + + /** + * Constructs a client from the given options. + * + * @param options the options to configure the client with. + * @return a new client. + * @throws AblyException if the options are invalid, for example if they carry no + * authentication parameters. + */ + public static PubSubRealtimeClient create(ClientOptions options) throws AblyException { + return new PubSubRealtimeClient(options); + } +} diff --git a/lib/src/main/java/io/ably/lib/transport/ConnectionManager.java b/lib/src/main/java/io/ably/pubsub/transport/ConnectionManager.java similarity index 96% rename from lib/src/main/java/io/ably/lib/transport/ConnectionManager.java rename to lib/src/main/java/io/ably/pubsub/transport/ConnectionManager.java index d39f65a34..850159c4d 100644 --- a/lib/src/main/java/io/ably/lib/transport/ConnectionManager.java +++ b/lib/src/main/java/io/ably/pubsub/transport/ConnectionManager.java @@ -1,4 +1,4 @@ -package io.ably.lib.transport; +package io.ably.pubsub.transport; import java.util.ArrayDeque; import java.util.ArrayList; @@ -11,36 +11,36 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; -import io.ably.lib.debug.DebugOptions; -import io.ably.lib.debug.DebugOptions.RawProtocolListener; -import io.ably.lib.http.HttpHelpers; -import io.ably.lib.liveobjects.LiveObjectsPlugin; -import io.ably.lib.realtime.AblyRealtime; -import io.ably.lib.realtime.Channel; -import io.ably.lib.realtime.ChannelState; -import io.ably.lib.realtime.CompletionListener; -import io.ably.lib.realtime.Connection; -import io.ably.lib.realtime.ConnectionState; -import io.ably.lib.realtime.ConnectionStateListener; -import io.ably.lib.realtime.ConnectionStateListener.ConnectionStateChange; -import io.ably.lib.rest.Auth; -import io.ably.lib.transport.ITransport.ConnectListener; -import io.ably.lib.transport.ITransport.TransportParams; -import io.ably.lib.transport.NetworkConnectivity.NetworkConnectivityListener; -import io.ably.lib.types.AblyException; -import io.ably.lib.types.Callback; -import io.ably.lib.types.ClientOptions; -import io.ably.lib.types.ConnectionDetails; -import io.ably.lib.types.ErrorInfo; -import io.ably.lib.types.Param; -import io.ably.lib.types.ProtocolMessage; -import io.ably.lib.types.ProtocolSerializer; -import io.ably.lib.types.PublishResult; -import io.ably.lib.util.Clock; -import io.ably.lib.util.Log; -import io.ably.lib.util.PlatformAgentProvider; -import io.ably.lib.util.ReconnectionStrategy; -import io.ably.lib.util.SystemClock; +import io.ably.pubsub.debug.DebugOptions; +import io.ably.pubsub.debug.DebugOptions.RawProtocolListener; +import io.ably.pubsub.http.HttpHelpers; +import io.ably.pubsub.liveobjects.LiveObjectsPlugin; +import io.ably.pubsub.realtime.PubSubRealtimeClient; +import io.ably.pubsub.realtime.Channel; +import io.ably.pubsub.realtime.ChannelState; +import io.ably.pubsub.realtime.CompletionListener; +import io.ably.pubsub.realtime.Connection; +import io.ably.pubsub.realtime.ConnectionState; +import io.ably.pubsub.realtime.ConnectionStateListener; +import io.ably.pubsub.realtime.ConnectionStateListener.ConnectionStateChange; +import io.ably.pubsub.http.Auth; +import io.ably.pubsub.transport.ITransport.ConnectListener; +import io.ably.pubsub.transport.ITransport.TransportParams; +import io.ably.pubsub.transport.NetworkConnectivity.NetworkConnectivityListener; +import io.ably.pubsub.types.AblyException; +import io.ably.pubsub.types.Callback; +import io.ably.pubsub.types.ClientOptions; +import io.ably.pubsub.types.ConnectionDetails; +import io.ably.pubsub.types.ErrorInfo; +import io.ably.pubsub.types.Param; +import io.ably.pubsub.types.ProtocolMessage; +import io.ably.pubsub.types.ProtocolSerializer; +import io.ably.pubsub.types.PublishResult; +import io.ably.pubsub.util.Clock; +import io.ably.pubsub.util.Log; +import io.ably.pubsub.util.PlatformAgentProvider; +import io.ably.pubsub.util.ReconnectionStrategy; +import io.ably.pubsub.util.SystemClock; import org.jetbrains.annotations.Nullable; public class ConnectionManager implements ConnectListener { @@ -109,7 +109,7 @@ public class ConnectionManager implements ConnectListener { public Long objectsGCGracePeriod = null; /** - * Methods on the channels map owned by the {@link AblyRealtime} instance + * Methods on the channels map owned by the {@link PubSubRealtimeClient} instance * which the {@link ConnectionManager} needs access to. */ public interface Channels { @@ -782,7 +782,7 @@ public void run() { * ConnectionManager ***********************/ - public ConnectionManager(final AblyRealtime ably, final Connection connection, final Channels channels, final PlatformAgentProvider platformAgentProvider, LiveObjectsPlugin liveObjectsPlugin) throws AblyException { + public ConnectionManager(final PubSubRealtimeClient ably, final Connection connection, final Channels channels, final PlatformAgentProvider platformAgentProvider, LiveObjectsPlugin liveObjectsPlugin) throws AblyException { this.ably = ably; this.clock = SystemClock.clockFrom(ably.options); this.connection = connection; @@ -791,7 +791,7 @@ public ConnectionManager(final AblyRealtime ably, final Connection connection, f this.liveObjectsPlugin = liveObjectsPlugin; ClientOptions options = ably.options; - this.hosts = new Hosts(options.realtimeHost, Defaults.HOST_REALTIME, options); + this.hosts = new Hosts(options); /* debug options */ ITransport.Factory transportFactory = null; @@ -1286,7 +1286,6 @@ public void onMessage(ITransport transport, ProtocolMessage message) throws Ably private void onChannelMessage(ProtocolMessage message) { channels.onMessage(message); - connection.recoveryKey = connection.createRecoveryKey(); } private synchronized void onConnected(ProtocolMessage message) { @@ -1336,8 +1335,6 @@ private synchronized void onConnected(ProtocolMessage message) { return; } - connection.recoveryKey = connection.createRecoveryKey(); - /* indicated connected currentState */ final StateIndication stateIndication = new StateIndication(ConnectionState.connected, message.error, null, null); requestState(stateIndication); @@ -1460,7 +1457,6 @@ private boolean checkConnectionStale() { if(connection.key != null) { Log.v(TAG, "Clearing stale connection key to suppress resume"); connection.key = null; - connection.recoveryKey = null; } return true; } @@ -1520,22 +1516,24 @@ private void handleReauth() { if (currentState.state == ConnectionState.connected) { Log.v(TAG, "Server initiated reauth"); - ErrorInfo errorInfo = null; - /* * It is a server initiated reauth, it is issued while previous token is still valid for ~30 seconds, * we have to clear cached token and get a new one */ try { - ably.auth.renew(); + /* the UPDATE event is emitted from the completion callback, so that it reports the + * outcome of the reauth rather than only the fact that one was started */ + ably.auth.renewAuth((success, tokenDetails, errorInfo) -> emitReauthUpdate(errorInfo)); } catch (AblyException e) { - errorInfo = e.errorInfo; + emitReauthUpdate(e.errorInfo); } + } + } - /* report connection currentState in UPDATE event */ - if (currentState.state == ConnectionState.connected) { - connection.emitUpdate(errorInfo); - } + /** Reports the outcome of a server initiated reauth in an UPDATE event, if still connected. */ + private void emitReauthUpdate(ErrorInfo errorInfo) { + if (currentState.state == ConnectionState.connected) { + connection.emitUpdate(errorInfo); } } @@ -2022,7 +2020,7 @@ private boolean isFatalError(ErrorInfo err) { * private members ******************/ - final AblyRealtime ably; + final PubSubRealtimeClient ably; private final Clock clock; private final Channels channels; private final Connection connection; diff --git a/lib/src/main/java/io/ably/pubsub/transport/Defaults.java b/lib/src/main/java/io/ably/pubsub/transport/Defaults.java new file mode 100644 index 000000000..e22be2809 --- /dev/null +++ b/lib/src/main/java/io/ably/pubsub/transport/Defaults.java @@ -0,0 +1,142 @@ +package io.ably.pubsub.transport; + +import io.ably.pubsub.BuildConfig; +import io.ably.pubsub.types.ClientOptions; + +public class Defaults { + /** + * The level of compatibility with the Ably service that this SDK supports. + * Also referred to as the 'wire protocol version'. + * This value is presented as a string, as specified in G4a. + *

+ * spec: G4 + *

+ */ + public static final String ABLY_PROTOCOL_VERSION = "6"; + + /** + * The SDK family identifier. It renamed from {@code ably-java} with the per-side package + * split, so the identifier alone partitions the fleet: {@code ably-java/*} is legacy-package + * traffic, {@code ably-pubsub-java/*} is new-package traffic. It names the family rather than + * any one published artifact; the side a client declares travels as a separate versionless + * agent entry (see {@link io.ably.pubsub.util.Side} and the agents registry in ably-common). + */ + public static final String ABLY_AGENT_VERSION = String.format("%s/%s", "ably-pubsub-java", BuildConfig.VERSION); + + /* realtime params */ + public static final String ABLY_PROTOCOL_VERSION_PARAM = "v"; + public static final String ABLY_AGENT_PARAM = "agent"; + + /* http headers */ + public static final String ABLY_PROTOCOL_VERSION_HEADER = "X-Ably-Version"; + public static final String ABLY_CLIENT_ID_HEADER = "X-Ably-ClientId"; + public static final String ABLY_AGENT_HEADER = "Ably-Agent"; + + /* Hosts */ + /* REC1a: the endpoint used when ClientOptions#endpoint is unset */ + public static final String ENDPOINT = "main"; + /* REC2c1: the fallback domains for the default endpoint */ + public static final String[] HOST_FALLBACKS = getEndpointFallbackHosts(ENDPOINT); + public static final int PORT = 80; + public static final int TLS_PORT = 443; + + /* Timeouts */ + public static int TIMEOUT_CONNECT = 15000; + public static int TIMEOUT_DISCONNECT = 15000; + public static int TIMEOUT_CHANNEL_RETRY = 15000; + + /* TO3l3 */ + public static int TIMEOUT_HTTP_OPEN = 4000; + /* TO3l4 */ + public static int TIMEOUT_HTTP_REQUEST = 10000; + /* TO3l6 */ + public static int httpMaxRetryDuration = 15000; + + /* DF1b */ + public static long realtimeRequestTimeout = 10000L; + /* TO3l2 */ + public static long suspendedRetryTimeout = 30000L; + /* TO3l10 */ + public static long fallbackRetryTimeout = 10*60*1000L; + /* CD2h (but no default in the spec) */ + public static long maxIdleInterval = 20000L; + // 64kB, as per CD2c + public static int maxMessageSize = 65536; + /* DF1a */ + public static long connectionStateTtl = 120000L; + + public static final ITransport.Factory TRANSPORT = new WebSocketTransport.Factory(); + public static final int HTTP_MAX_RETRY_COUNT = 3; + public static final int HTTP_ASYNC_THREADPOOL_SIZE = 64; + + public static int getPort(ClientOptions options) { + return options.tls + ? ((options.tlsPort != 0) ? options.tlsPort : Defaults.TLS_PORT) + : ((options.port != 0) ? options.port : Defaults.PORT); + } + + /** + * Resolves the primary domain that both REST requests and realtime connections use. + *

+ * Spec: REC1 + * + * @param endpoint the configured endpoint, or null for the default + * @return the primary domain + */ + public static String getPrimaryDomain(String endpoint) { + if (endpoint == null) { + endpoint = ENDPOINT; + } + /* REC1b2 */ + if (isHostname(endpoint)) { + return endpoint; + } + /* REC1b3 */ + if (endpoint.startsWith(NONPROD_PREFIX)) { + return endpoint.substring(NONPROD_PREFIX.length()) + ".realtime.ably-nonprod.net"; + } + /* REC1b4 */ + return endpoint + ".realtime.ably.net"; + } + + /** + * Resolves the default fallback domains for an endpoint, used when ClientOptions#fallbackHosts is unset. + *

+ * Spec: REC2c + * + * @param endpoint the configured endpoint, or null for the default + * @return the fallback domains; empty when the endpoint is a hostname + */ + public static String[] getEndpointFallbackHosts(String endpoint) { + if (endpoint == null) { + endpoint = ENDPOINT; + } + /* REC2c2 */ + if (isHostname(endpoint)) { + return new String[0]; + } + /* REC2c3 */ + if (endpoint.startsWith(NONPROD_PREFIX)) { + return fallbackHosts(endpoint.substring(NONPROD_PREFIX.length()), "ably-realtime-nonprod.com"); + } + /* REC2c1, REC2c4 */ + return fallbackHosts(endpoint, "ably-realtime.com"); + } + + private static final String NONPROD_PREFIX = "nonprod:"; + + /* REC1b2: an endpoint is a hostname if it contains '.' or '::', or is "localhost" */ + private static boolean isHostname(String endpoint) { + return endpoint.contains(".") || endpoint.contains("::") || endpoint.equals("localhost"); + } + + private static String[] fallbackHosts(String routingPolicyId, String domain) { + return new String[] { + routingPolicyId + ".a.fallback." + domain, + routingPolicyId + ".b.fallback." + domain, + routingPolicyId + ".c.fallback." + domain, + routingPolicyId + ".d.fallback." + domain, + routingPolicyId + ".e.fallback." + domain + }; + } +} diff --git a/lib/src/main/java/io/ably/pubsub/transport/Hosts.java b/lib/src/main/java/io/ably/pubsub/transport/Hosts.java new file mode 100644 index 000000000..acb6644ff --- /dev/null +++ b/lib/src/main/java/io/ably/pubsub/transport/Hosts.java @@ -0,0 +1,142 @@ +package io.ably.pubsub.transport; + +import io.ably.pubsub.types.ClientOptions; +import io.ably.pubsub.util.Clock; +import io.ably.pubsub.util.SystemClock; + +import java.util.Arrays; +import java.util.Collections; + + +/** + * Object to encapsulate primary host name and shuffled fallback host names. + * + * Methods on this class are safe to be called from any thread. + */ +public class Hosts { + private final String primaryHost; + private final String[] fallbackHosts; + private final long fallbackRetryTimeout; + + private final Preferred preferred = new Preferred(); + private final Clock clock; + + /** + * Create Hosts object + * + * @param options ClientOptions to get endpoint and fallbackHosts from + * + * REST requests and realtime connections share the same primary domain (RSC25, RTN2), + * so an HttpCore and a ConnectionManager built from the same options resolve the same hosts. + */ + public Hosts(final ClientOptions options) { + /* REC1 */ + this.primaryHost = Defaults.getPrimaryDomain(options.endpoint); + /* REC2a2: explicit fallbackHosts always replace the defaults; REC2c: otherwise derive them from the endpoint */ + String[] tempFallbackHosts = options.fallbackHosts != null + ? options.fallbackHosts + : Defaults.getEndpointFallbackHosts(options.endpoint); + fallbackHosts = tempFallbackHosts.clone(); + /* RSC15a: shuffle the fallback hosts. */ + Collections.shuffle(Arrays.asList(fallbackHosts)); + fallbackRetryTimeout = options.fallbackRetryTimeout; + this.clock = SystemClock.clockFrom(options); + } + + /** + * set preferred hostname, which might not be the primary + */ + public synchronized void setPreferredHost(final String prefHost, final boolean temporary) { + if (preferred.isHost(prefHost)) { + /* a successful request against a fallback; don't update the expiry time */ + return; + } + if(prefHost.equals(primaryHost)) { + /* a successful request against the primary host; reset */ + preferred.clear(); + } else { + preferred.setHost(prefHost, temporary ? clock.currentTimeMillis() + fallbackRetryTimeout : 0); + } + } + + /** + * Get primary host name + */ + public String getPrimaryHost() { + return primaryHost; + } + + /** + * Get preferred host name (taking into account any affinity to a fallback: see RSC15f) + */ + public synchronized String getPreferredHost() { + final String host = preferred.getHostOrClearIfExpired(clock); + return (host == null) ? primaryHost : host; + } + + /** + * Get next fallback host if any + * + * @param lastHost + * @return Successor host that can be used as a fallback. + * null, if there is no successor fallback available. + */ + public synchronized String getFallback(String lastHost) { + int idx; + if (lastHost.equals(primaryHost)) { + idx = 0; + } else if(lastHost.equals(preferred.getHostOrClearIfExpired(clock))) { + /* RSC15f: there was a failure on an unexpired, cached fallback; so try again using the primary */ + preferred.clear(); + return primaryHost; + } else { + /* Onto next fallback. */ + idx = Arrays.asList(fallbackHosts).indexOf(lastHost); + if (idx < 0) { + return null; + } + ++idx; + } + if (idx >= fallbackHosts.length) { + return null; + } + return fallbackHosts[idx]; + } + + public synchronized int fallbackHostsRemaining(String candidateHost) { + if(candidateHost.equals(primaryHost) || candidateHost.equals(preferred.getHost())) { + return fallbackHosts.length; + } + return fallbackHosts.length - Arrays.asList(fallbackHosts).indexOf(candidateHost) - 1; + } + + private static class Preferred { + private String host; + private long expiry; + + public void clear() { + host = null; + expiry = 0; + } + + public boolean isHost(final String host) { + return (this.host == null) ? (host == null) : this.host.equals(host); + } + + public void setHost(final String host, final long expiry) { + this.host = host; + this.expiry = expiry; + } + + public String getHostOrClearIfExpired(Clock clock) { + if(expiry > 0 && expiry <= clock.currentTimeMillis()) { + clear(); // expired, so reset + } + return host; + } + + public String getHost() { + return host; + } + } +} diff --git a/lib/src/main/java/io/ably/lib/transport/ITransport.java b/lib/src/main/java/io/ably/pubsub/transport/ITransport.java similarity index 89% rename from lib/src/main/java/io/ably/lib/transport/ITransport.java rename to lib/src/main/java/io/ably/pubsub/transport/ITransport.java index cdcbf92b5..eb49189ca 100644 --- a/lib/src/main/java/io/ably/lib/transport/ITransport.java +++ b/lib/src/main/java/io/ably/pubsub/transport/ITransport.java @@ -1,15 +1,15 @@ -package io.ably.lib.transport; - -import io.ably.lib.types.AblyException; -import io.ably.lib.types.ClientOptions; -import io.ably.lib.types.ErrorInfo; -import io.ably.lib.types.Param; -import io.ably.lib.types.ProtocolMessage; -import io.ably.lib.types.RecoveryKeyContext; -import io.ably.lib.util.AgentHeaderCreator; -import io.ably.lib.util.Log; -import io.ably.lib.util.PlatformAgentProvider; -import io.ably.lib.util.StringUtils; +package io.ably.pubsub.transport; + +import io.ably.pubsub.types.AblyException; +import io.ably.pubsub.types.ClientOptions; +import io.ably.pubsub.types.ErrorInfo; +import io.ably.pubsub.types.Param; +import io.ably.pubsub.types.ProtocolMessage; +import io.ably.pubsub.types.RecoveryKeyContext; +import io.ably.pubsub.util.AgentHeaderCreator; +import io.ably.pubsub.util.Log; +import io.ably.pubsub.util.PlatformAgentProvider; +import io.ably.pubsub.util.StringUtils; import java.io.IOException; import java.util.ArrayList; diff --git a/lib/src/main/java/io/ably/lib/transport/NetworkConnectivity.java b/lib/src/main/java/io/ably/pubsub/transport/NetworkConnectivity.java similarity index 96% rename from lib/src/main/java/io/ably/lib/transport/NetworkConnectivity.java rename to lib/src/main/java/io/ably/pubsub/transport/NetworkConnectivity.java index bc1f09823..7b9a83070 100644 --- a/lib/src/main/java/io/ably/lib/transport/NetworkConnectivity.java +++ b/lib/src/main/java/io/ably/pubsub/transport/NetworkConnectivity.java @@ -1,6 +1,6 @@ -package io.ably.lib.transport; +package io.ably.pubsub.transport; -import io.ably.lib.types.ErrorInfo; +import io.ably.pubsub.types.ErrorInfo; import java.util.HashSet; import java.util.Set; diff --git a/lib/src/main/java/io/ably/lib/transport/SafeSSLSocketFactory.java b/lib/src/main/java/io/ably/pubsub/transport/SafeSSLSocketFactory.java similarity index 99% rename from lib/src/main/java/io/ably/lib/transport/SafeSSLSocketFactory.java rename to lib/src/main/java/io/ably/pubsub/transport/SafeSSLSocketFactory.java index c8fc5d6b3..967facdbc 100644 --- a/lib/src/main/java/io/ably/lib/transport/SafeSSLSocketFactory.java +++ b/lib/src/main/java/io/ably/pubsub/transport/SafeSSLSocketFactory.java @@ -1,4 +1,4 @@ -package io.ably.lib.transport; +package io.ably.pubsub.transport; import javax.net.ssl.SSLSocket; import javax.net.ssl.SSLSocketFactory; diff --git a/lib/src/main/java/io/ably/lib/transport/WebSocketTransport.java b/lib/src/main/java/io/ably/pubsub/transport/WebSocketTransport.java similarity index 93% rename from lib/src/main/java/io/ably/lib/transport/WebSocketTransport.java rename to lib/src/main/java/io/ably/pubsub/transport/WebSocketTransport.java index ed20cde81..87cb923e9 100644 --- a/lib/src/main/java/io/ably/lib/transport/WebSocketTransport.java +++ b/lib/src/main/java/io/ably/pubsub/transport/WebSocketTransport.java @@ -1,25 +1,25 @@ -package io.ably.lib.transport; - -import io.ably.lib.debug.DebugOptions; -import io.ably.lib.http.HttpUtils; -import io.ably.lib.network.EngineType; -import io.ably.lib.network.NotConnectedException; -import io.ably.lib.network.WebSocketClient; -import io.ably.lib.network.WebSocketEngine; -import io.ably.lib.network.WebSocketEngineConfig; -import io.ably.lib.network.WebSocketEngineFactory; -import io.ably.lib.network.WebSocketListener; -import io.ably.lib.types.AblyException; -import io.ably.lib.types.ErrorInfo; -import io.ably.lib.types.Param; -import io.ably.lib.types.ProtocolMessage; -import io.ably.lib.types.ProtocolSerializer; -import io.ably.lib.util.Clock; -import io.ably.lib.util.ClientOptionsUtils; -import io.ably.lib.util.Log; -import io.ably.lib.util.AblyTimer; -import io.ably.lib.util.SystemClock; -import io.ably.lib.util.TimerInstance; +package io.ably.pubsub.transport; + +import io.ably.pubsub.debug.DebugOptions; +import io.ably.pubsub.http.HttpUtils; +import io.ably.pubsub.network.EngineType; +import io.ably.pubsub.network.NotConnectedException; +import io.ably.pubsub.network.WebSocketClient; +import io.ably.pubsub.network.WebSocketEngine; +import io.ably.pubsub.network.WebSocketEngineConfig; +import io.ably.pubsub.network.WebSocketEngineFactory; +import io.ably.pubsub.network.WebSocketListener; +import io.ably.pubsub.types.AblyException; +import io.ably.pubsub.types.ErrorInfo; +import io.ably.pubsub.types.Param; +import io.ably.pubsub.types.ProtocolMessage; +import io.ably.pubsub.types.ProtocolSerializer; +import io.ably.pubsub.util.Clock; +import io.ably.pubsub.util.ClientOptionsUtils; +import io.ably.pubsub.util.Log; +import io.ably.pubsub.util.AblyTimer; +import io.ably.pubsub.util.SystemClock; +import io.ably.pubsub.util.TimerInstance; import javax.net.ssl.SSLContext; import java.nio.ByteBuffer; @@ -118,7 +118,7 @@ public void connect(ConnectListener connectListener) { try { boolean isTls = params.options.tls; String wsScheme = isTls ? "wss://" : "ws://"; - wsUri = wsScheme + params.host + ':' + params.port + "/"; + wsUri = wsScheme + HttpUtils.hostForUrl(params.host) + ':' + params.port + "/"; Param[] authParams = connectionManager.getAuthParams(); Param[] connectParams = params.getConnectParams(authParams); if (connectParams.length > 0) @@ -216,7 +216,7 @@ protected void preProcessReceivedMessage(ProtocolMessage message) { /** * Visible For Testing *

- * We need to turn off activity check for some tests (e.g. io.ably.lib.test.realtime.RealtimeConnectFailTest.disconnect_retry_channel_timeout_jitter_after_consistent_detach[binary_protocol]) + * We need to turn off activity check for some tests (e.g. io.ably.pubsub.test.realtime.RealtimeConnectFailTest.disconnect_retry_channel_timeout_jitter_after_consistent_detach[binary_protocol]) * Those tests expects that activity checks are passing, but protocol messages are not coming */ protected void turnOffActivityCheckIfPingListenerIsNotSupported() { diff --git a/lib/src/main/java/io/ably/lib/types/AblyException.java b/lib/src/main/java/io/ably/pubsub/types/AblyException.java similarity index 96% rename from lib/src/main/java/io/ably/lib/types/AblyException.java rename to lib/src/main/java/io/ably/pubsub/types/AblyException.java index d7a531d97..bde263daf 100644 --- a/lib/src/main/java/io/ably/lib/types/AblyException.java +++ b/lib/src/main/java/io/ably/pubsub/types/AblyException.java @@ -1,6 +1,6 @@ -package io.ably.lib.types; +package io.ably.pubsub.types; -import io.ably.lib.network.FailedConnectionException; +import io.ably.pubsub.network.FailedConnectionException; import java.net.ConnectException; import java.net.NoRouteToHostException; import java.net.SocketTimeoutException; diff --git a/lib/src/main/java/io/ably/lib/types/Annotation.java b/lib/src/main/java/io/ably/pubsub/types/Annotation.java similarity index 98% rename from lib/src/main/java/io/ably/lib/types/Annotation.java rename to lib/src/main/java/io/ably/pubsub/types/Annotation.java index 73821d3f2..643bbeef6 100644 --- a/lib/src/main/java/io/ably/lib/types/Annotation.java +++ b/lib/src/main/java/io/ably/pubsub/types/Annotation.java @@ -1,4 +1,4 @@ -package io.ably.lib.types; +package io.ably.pubsub.types; import com.google.gson.JsonDeserializationContext; import com.google.gson.JsonDeserializer; @@ -8,8 +8,8 @@ import com.google.gson.JsonPrimitive; import com.google.gson.JsonSerializationContext; import com.google.gson.JsonSerializer; -import io.ably.lib.util.Log; -import io.ably.lib.util.Serialisation; +import io.ably.pubsub.util.Log; +import io.ably.pubsub.util.Serialisation; import org.jetbrains.annotations.NotNull; import org.msgpack.core.MessageFormat; import org.msgpack.core.MessagePacker; diff --git a/lib/src/main/java/io/ably/lib/types/AnnotationAction.java b/lib/src/main/java/io/ably/pubsub/types/AnnotationAction.java similarity index 93% rename from lib/src/main/java/io/ably/lib/types/AnnotationAction.java rename to lib/src/main/java/io/ably/pubsub/types/AnnotationAction.java index 732cde594..0032ba3be 100644 --- a/lib/src/main/java/io/ably/lib/types/AnnotationAction.java +++ b/lib/src/main/java/io/ably/pubsub/types/AnnotationAction.java @@ -1,4 +1,4 @@ -package io.ably.lib.types; +package io.ably.pubsub.types; /** * Enumerates the possible values of the {@link Annotation#action} field of an {@link Annotation} diff --git a/lib/src/main/java/io/ably/lib/types/AnnotationSerializer.java b/lib/src/main/java/io/ably/pubsub/types/AnnotationSerializer.java similarity index 95% rename from lib/src/main/java/io/ably/lib/types/AnnotationSerializer.java rename to lib/src/main/java/io/ably/pubsub/types/AnnotationSerializer.java index 88d7c59ff..a70095d1e 100644 --- a/lib/src/main/java/io/ably/lib/types/AnnotationSerializer.java +++ b/lib/src/main/java/io/ably/pubsub/types/AnnotationSerializer.java @@ -1,9 +1,9 @@ -package io.ably.lib.types; +package io.ably.pubsub.types; -import io.ably.lib.http.HttpCore; -import io.ably.lib.http.HttpUtils; -import io.ably.lib.util.Log; -import io.ably.lib.util.Serialisation; +import io.ably.pubsub.http.HttpCore; +import io.ably.pubsub.http.HttpUtils; +import io.ably.pubsub.util.Log; +import io.ably.pubsub.util.Serialisation; import org.msgpack.core.MessagePacker; import org.msgpack.core.MessageUnpacker; diff --git a/lib/src/main/java/io/ably/lib/types/AsyncHttpPaginatedResponse.java b/lib/src/main/java/io/ably/pubsub/types/AsyncHttpPaginatedResponse.java similarity index 97% rename from lib/src/main/java/io/ably/lib/types/AsyncHttpPaginatedResponse.java rename to lib/src/main/java/io/ably/pubsub/types/AsyncHttpPaginatedResponse.java index f124228fc..5904bd5a8 100644 --- a/lib/src/main/java/io/ably/lib/types/AsyncHttpPaginatedResponse.java +++ b/lib/src/main/java/io/ably/pubsub/types/AsyncHttpPaginatedResponse.java @@ -1,4 +1,4 @@ -package io.ably.lib.types; +package io.ably.pubsub.types; import com.google.gson.JsonElement; diff --git a/lib/src/main/java/io/ably/lib/types/AsyncPaginatedResult.java b/lib/src/main/java/io/ably/pubsub/types/AsyncPaginatedResult.java similarity index 97% rename from lib/src/main/java/io/ably/lib/types/AsyncPaginatedResult.java rename to lib/src/main/java/io/ably/pubsub/types/AsyncPaginatedResult.java index dd33f27a7..44ae159a2 100644 --- a/lib/src/main/java/io/ably/lib/types/AsyncPaginatedResult.java +++ b/lib/src/main/java/io/ably/pubsub/types/AsyncPaginatedResult.java @@ -1,4 +1,4 @@ -package io.ably.lib.types; +package io.ably.pubsub.types; /** * A type that represents a page of results from a paginated query. diff --git a/lib/src/main/java/io/ably/lib/types/BaseMessage.java b/lib/src/main/java/io/ably/pubsub/types/BaseMessage.java similarity index 98% rename from lib/src/main/java/io/ably/lib/types/BaseMessage.java rename to lib/src/main/java/io/ably/pubsub/types/BaseMessage.java index 8e3b234ee..f4d9392ab 100644 --- a/lib/src/main/java/io/ably/lib/types/BaseMessage.java +++ b/lib/src/main/java/io/ably/pubsub/types/BaseMessage.java @@ -1,4 +1,4 @@ -package io.ably.lib.types; +package io.ably.pubsub.types; import com.davidehrmann.vcdiff.VCDiffDecoder; import com.davidehrmann.vcdiff.VCDiffDecoderBuilder; @@ -7,12 +7,12 @@ import com.google.gson.JsonObject; import com.google.gson.JsonParseException; import com.google.gson.JsonPrimitive; -import io.ably.lib.util.Base64Coder; -import io.ably.lib.util.Crypto; -import io.ably.lib.util.Crypto.EncryptingChannelCipher; -import io.ably.lib.util.Crypto.DecryptingChannelCipher; -import io.ably.lib.util.Log; -import io.ably.lib.util.Serialisation; +import io.ably.pubsub.util.Base64Coder; +import io.ably.pubsub.util.Crypto; +import io.ably.pubsub.util.Crypto.EncryptingChannelCipher; +import io.ably.pubsub.util.Crypto.DecryptingChannelCipher; +import io.ably.pubsub.util.Log; +import io.ably.pubsub.util.Serialisation; import org.msgpack.core.MessageFormat; import org.msgpack.core.MessagePacker; import org.msgpack.core.MessageUnpacker; diff --git a/lib/src/main/java/io/ably/lib/types/BasePaginatedResult.java b/lib/src/main/java/io/ably/pubsub/types/BasePaginatedResult.java similarity index 72% rename from lib/src/main/java/io/ably/lib/types/BasePaginatedResult.java rename to lib/src/main/java/io/ably/pubsub/types/BasePaginatedResult.java index 7c4b6edc7..f9d067cbd 100644 --- a/lib/src/main/java/io/ably/lib/types/BasePaginatedResult.java +++ b/lib/src/main/java/io/ably/pubsub/types/BasePaginatedResult.java @@ -1,6 +1,6 @@ -package io.ably.lib.types; +package io.ably.pubsub.types; -import io.ably.lib.http.Http; +import io.ably.pubsub.http.HttpRequester; /** * A type that represents a page of results from a paginated query. @@ -21,9 +21,9 @@ public interface BasePaginatedResult { /** * Perform the given relative query */ - Http.Request> first(); - Http.Request> current(); - Http.Request> next(); + HttpRequester.Request> first(); + HttpRequester.Request> current(); + HttpRequester.Request> next(); boolean hasFirst(); boolean hasCurrent(); diff --git a/lib/src/main/java/io/ably/lib/types/Callback.java b/lib/src/main/java/io/ably/pubsub/types/Callback.java similarity index 92% rename from lib/src/main/java/io/ably/lib/types/Callback.java rename to lib/src/main/java/io/ably/pubsub/types/Callback.java index 1ff17e009..284725d5c 100644 --- a/lib/src/main/java/io/ably/lib/types/Callback.java +++ b/lib/src/main/java/io/ably/pubsub/types/Callback.java @@ -1,6 +1,6 @@ -package io.ably.lib.types; +package io.ably.pubsub.types; -import io.ably.lib.types.ErrorInfo; +import io.ably.pubsub.types.ErrorInfo; /** * An interface allowing a client to be notified of the outcome diff --git a/lib/src/main/java/io/ably/lib/types/Capability.java b/lib/src/main/java/io/ably/pubsub/types/Capability.java similarity index 99% rename from lib/src/main/java/io/ably/lib/types/Capability.java rename to lib/src/main/java/io/ably/pubsub/types/Capability.java index 369f1cd74..066570782 100644 --- a/lib/src/main/java/io/ably/lib/types/Capability.java +++ b/lib/src/main/java/io/ably/pubsub/types/Capability.java @@ -1,4 +1,4 @@ -package io.ably.lib.types; +package io.ably.pubsub.types; import java.util.Arrays; diff --git a/lib/src/main/java/io/ably/lib/types/ChannelMode.java b/lib/src/main/java/io/ably/pubsub/types/ChannelMode.java similarity index 95% rename from lib/src/main/java/io/ably/lib/types/ChannelMode.java rename to lib/src/main/java/io/ably/pubsub/types/ChannelMode.java index f20636933..5ca3ce4a3 100644 --- a/lib/src/main/java/io/ably/lib/types/ChannelMode.java +++ b/lib/src/main/java/io/ably/pubsub/types/ChannelMode.java @@ -1,9 +1,9 @@ -package io.ably.lib.types; +package io.ably.pubsub.types; import java.util.HashSet; import java.util.Set; -import io.ably.lib.types.ProtocolMessage.Flag; +import io.ably.pubsub.types.ProtocolMessage.Flag; /** * Describes the possible flags used to configure client capabilities, using {@link ChannelOptions}. diff --git a/lib/src/main/java/io/ably/lib/types/ChannelOptions.java b/lib/src/main/java/io/ably/pubsub/types/ChannelOptions.java similarity index 68% rename from lib/src/main/java/io/ably/lib/types/ChannelOptions.java rename to lib/src/main/java/io/ably/pubsub/types/ChannelOptions.java index bda871c9b..0918c2d73 100644 --- a/lib/src/main/java/io/ably/lib/types/ChannelOptions.java +++ b/lib/src/main/java/io/ably/pubsub/types/ChannelOptions.java @@ -1,13 +1,13 @@ -package io.ably.lib.types; +package io.ably.pubsub.types; import java.util.Map; -import io.ably.lib.util.Base64Coder; -import io.ably.lib.util.Crypto; -import io.ably.lib.util.Crypto.CipherParams; +import io.ably.pubsub.util.Base64Coder; +import io.ably.pubsub.util.Crypto; +import io.ably.pubsub.util.Crypto.CipherParams; /** - * Passes additional properties to a {@link io.ably.lib.rest.Channel} or {@link io.ably.lib.realtime.Channel} object, + * Passes additional properties to a {@link io.ably.pubsub.http.Channel} or {@link io.ably.pubsub.realtime.Channel} object, * such as encryption, {@link ChannelMode} and channel parameters. */ public class ChannelOptions { @@ -42,8 +42,8 @@ public class ChannelOptions { /** *

- * Determines whether calling {@link io.ably.lib.realtime.Channel#subscribe Channel.subscribe} or - * {@link io.ably.lib.realtime.Presence#subscribe Presence.subscribe} method + * Determines whether calling {@link io.ably.pubsub.realtime.Channel#subscribe Channel.subscribe} or + * {@link io.ably.pubsub.realtime.Presence#subscribe Presence.subscribe} method * should trigger an implicit attach. *

*

Defaults to {@code true}.

@@ -67,30 +67,6 @@ public int getModeFlags() { return flags; } - /** - * Deprecated. Use withCipherKey(byte[]) instead.

- * Create ChannelOptions from the given cipher key. - * @param key Byte array cipher key. - * @return Created ChannelOptions. - * @throws AblyException If something goes wrong. - */ - @Deprecated - public static ChannelOptions fromCipherKey(byte[] key) throws AblyException { - return withCipherKey(key); - } - - /** - * Deprecated. Use withCipherKey(String) instead.

- * Create ChannelOptions from the given cipher key. - * @param base64Key The cipher key as a base64-encoded String, - * @return Created ChannelOptions. - * @throws AblyException If something goes wrong. - */ - @Deprecated - public static ChannelOptions fromCipherKey(String base64Key) throws AblyException { - return fromCipherKey(Base64Coder.decode(base64Key)); - } - /** * Constructor withCipherKey, that takes a key only. *

diff --git a/lib/src/main/java/io/ably/lib/types/ChannelProperties.java b/lib/src/main/java/io/ably/pubsub/types/ChannelProperties.java similarity index 72% rename from lib/src/main/java/io/ably/lib/types/ChannelProperties.java rename to lib/src/main/java/io/ably/pubsub/types/ChannelProperties.java index 482528d18..f38756dbe 100644 --- a/lib/src/main/java/io/ably/lib/types/ChannelProperties.java +++ b/lib/src/main/java/io/ably/pubsub/types/ChannelProperties.java @@ -1,4 +1,4 @@ -package io.ably.lib.types; +package io.ably.pubsub.types; /** * Describes the properties of the channel state. @@ -9,8 +9,8 @@ public class ChannelProperties { /** * Starts unset when a channel is instantiated, then updated with the channelSerial - * from each {@link io.ably.lib.realtime.ChannelState#attached} event that matches the channel. - * Used as the value for {@link io.ably.lib.realtime.Channel#history}. + * from each {@link io.ably.pubsub.realtime.ChannelState#attached} event that matches the channel. + * Used as the value for {@link io.ably.pubsub.realtime.Channel#history}. *

* Spec: CP2a */ diff --git a/lib/src/main/java/io/ably/lib/types/ClientOptions.java b/lib/src/main/java/io/ably/pubsub/types/ClientOptions.java similarity index 85% rename from lib/src/main/java/io/ably/lib/types/ClientOptions.java rename to lib/src/main/java/io/ably/pubsub/types/ClientOptions.java index 3d63be81a..1efa71418 100644 --- a/lib/src/main/java/io/ably/lib/types/ClientOptions.java +++ b/lib/src/main/java/io/ably/pubsub/types/ClientOptions.java @@ -1,16 +1,16 @@ -package io.ably.lib.types; +package io.ably.pubsub.types; -import io.ably.lib.push.Storage; -import io.ably.lib.rest.Auth.AuthOptions; -import io.ably.lib.rest.Auth.TokenParams; -import io.ably.lib.transport.Defaults; -import io.ably.lib.util.Log; -import io.ably.lib.util.Log.LogHandler; +import io.ably.pubsub.push.Storage; +import io.ably.pubsub.http.Auth.AuthOptions; +import io.ably.pubsub.http.Auth.TokenParams; +import io.ably.pubsub.transport.Defaults; +import io.ably.pubsub.util.Log; +import io.ably.pubsub.util.Log.LogHandler; import java.util.Map; /** - * Passes additional client-specific properties to the {@link io.ably.lib.rest.AblyRest} or the {@link io.ably.lib.realtime.AblyRealtime}. + * Passes additional client-specific properties to the {@link io.ably.pubsub.http.PubSubHttpClient} or the {@link io.ably.pubsub.realtime.PubSubRealtimeClient}. *

* Extends an {@link AuthOptions} object. *

@@ -19,12 +19,12 @@ public class ClientOptions extends AuthOptions { /** - * Creates a ClientOptions instance used to configure Rest and Realtime clients + * Creates a ClientOptions instance used to configure HTTP and Realtime clients */ public ClientOptions() {} /** - * Creates a ClientOptions instance used to configure Rest and Realtime clients + * Creates a ClientOptions instance used to configure HTTP and Realtime clients * * @param key the key obtained from the application dashboard. * @throws AblyException if the key is not in a valid format @@ -73,20 +73,19 @@ public ClientOptions(String key) throws AblyException { public Map headers; /** - * Enables a non-default Ably host to be specified. For development environments only. - * The default value is rest.ably.io. + * Sets the endpoint that both REST requests and realtime connections use. The value can be: + *

    + *
  • a routing policy name, such as {@code main}, which connects to {@code [name].realtime.ably.net};
  • + *
  • a nonprod routing policy name prefixed with {@code nonprod:}, such as {@code nonprod:sandbox}, + * which connects to {@code [name].realtime.ably-nonprod.net};
  • + *
  • a hostname (one containing {@code .} or {@code ::}, or {@code localhost}), which is used as given + * with no default fallback hosts.
  • + *
+ * The default is {@code main}. *

- * Spec: RSC12, TO3k2 + * Spec: REC1 */ - public String restHost; - - /** - * Enables a non-default Ably host to be specified for realtime connections. - * For development environments only. The default value is realtime.ably.io. - *

- * Spec: RTC1d, TO3k3 - */ - public String realtimeHost; + public String endpoint; /** * Enables a non-default Ably port to be specified. For development environments only. The default value is 80. @@ -106,7 +105,7 @@ public ClientOptions(String key) throws AblyException { /** * When true, the client connects to Ably as soon as it is instantiated. * You can set this to false and explicitly connect to Ably using the - * {@link io.ably.lib.realtime.Connection#connect} method. The default is true. + * {@link io.ably.pubsub.realtime.Connection#connect} method. The default is true. *

* Spec: RTC1b, TO3e */ @@ -157,13 +156,6 @@ public ClientOptions(String key) throws AblyException { */ public ProxyOptions proxy; - /** - * Enables a custom environment to be used with the Ably service. - *

- * Spec: RSC15b, TO3k1 - */ - public String environment; - /** * When true, enables idempotent publishing by assigning a unique message ID client-side, * allowing the Ably servers to discard automatic publish retries following a failure such as a network fault. @@ -228,8 +220,10 @@ public ClientOptions(String key) throws AblyException { /** * An array of fallback hosts to be used in the case of an error necessitating the use of an alternative host. * If you have been provided a set of custom fallback hosts by Ably, please specify them here. + * When set, these replace the default fallback hosts derived from {@link #endpoint}; + * an empty array disables fallback. *

- * Spec: RSC15b, RSC15a, TO3k6 + * Spec: REC2a2, RSC15a, TO3k6 */ public String[] fallbackHosts; @@ -242,15 +236,6 @@ public ClientOptions(String key) throws AblyException { */ public long suspendedRetryTimeout = Defaults.suspendedRetryTimeout; - /** - * An array of fallback hosts to be used in the case of an error necessitating the use of an alternative host. - * If you have been provided a set of custom fallback hosts by Ably, please specify them here. - *

- * Spec: RSC15b, RSC15a, TO3k6 - */ - @Deprecated - public boolean fallbackHostsUseDefault; - /** * The maximum time before HTTP requests are retried against the default endpoint. * The default is 600 seconds. @@ -261,17 +246,17 @@ public ClientOptions(String key) throws AblyException { /** * When a {@link TokenParams} object is provided, it overrides the client library - * defaults when issuing new Ably Tokens or Ably {@link io.ably.lib.rest.Auth.TokenRequest}. + * defaults when issuing new Ably Tokens or Ably {@link io.ably.pubsub.http.Auth.TokenRequest}. *

* Spec: TO3j11 */ public TokenParams defaultTokenParams = new TokenParams(); /** - * When a channel becomes {@link io.ably.lib.realtime.ChannelState#suspended} - * following a server initiated {@link io.ably.lib.realtime.ChannelState#detached}, - * after this delay, if the channel is still {@link io.ably.lib.realtime.ChannelState#suspended} - * and the connection is {@link io.ably.lib.realtime.ConnectionState#connected}, + * When a channel becomes {@link io.ably.pubsub.realtime.ChannelState#suspended} + * following a server initiated {@link io.ably.pubsub.realtime.ChannelState#detached}, + * after this delay, if the channel is still {@link io.ably.pubsub.realtime.ChannelState#suspended} + * and the connection is {@link io.ably.pubsub.realtime.ConnectionState#connected}, * the client library will attempt to re-attach the channel automatically. * The default is 15 seconds. *

@@ -335,8 +320,7 @@ public ClientOptions copy() { copied.logLevel = logLevel; copied.logHandler = logHandler; copied.tls = tls; - copied.restHost = restHost; - copied.realtimeHost = realtimeHost; + copied.endpoint = endpoint; copied.port = port; copied.tlsPort = tlsPort; copied.autoConnect = autoConnect; @@ -345,7 +329,6 @@ public ClientOptions copy() { copied.echoMessages = echoMessages; copied.recover = recover; copied.proxy = proxy; - copied.environment = environment; copied.idempotentRestPublishing = idempotentRestPublishing; copied.httpOpenTimeout = httpOpenTimeout; copied.httpRequestTimeout = httpRequestTimeout; @@ -354,7 +337,6 @@ public ClientOptions copy() { copied.realtimeRequestTimeout = realtimeRequestTimeout; copied.disconnectedRetryTimeout = disconnectedRetryTimeout; copied.suspendedRetryTimeout = suspendedRetryTimeout; - copied.fallbackHostsUseDefault = fallbackHostsUseDefault; copied.fallbackRetryTimeout = fallbackRetryTimeout; copied.defaultTokenParams = defaultTokenParams; copied.channelRetryTimeout = channelRetryTimeout; @@ -372,6 +354,10 @@ public ClientOptions copy() { copied.authParams = authParams; copied.queryTime = queryTime; copied.useTokenAuth = useTokenAuth; + copied.headers = headers; + copied.fallbackHosts = fallbackHosts; + copied.transportParams = transportParams; + copied.agents = agents; return copied; } diff --git a/lib/src/main/java/io/ably/lib/types/ConnectionDetails.java b/lib/src/main/java/io/ably/pubsub/types/ConnectionDetails.java similarity index 94% rename from lib/src/main/java/io/ably/lib/types/ConnectionDetails.java rename to lib/src/main/java/io/ably/pubsub/types/ConnectionDetails.java index 6a557a12a..0ffa9c61d 100644 --- a/lib/src/main/java/io/ably/lib/types/ConnectionDetails.java +++ b/lib/src/main/java/io/ably/pubsub/types/ConnectionDetails.java @@ -1,16 +1,16 @@ -package io.ably.lib.types; +package io.ably.pubsub.types; import java.io.IOException; -import io.ably.lib.transport.Defaults; -import io.ably.lib.util.Log; +import io.ably.pubsub.transport.Defaults; +import io.ably.pubsub.util.Log; import org.msgpack.core.MessageFormat; import org.msgpack.core.MessageUnpacker; /** - * Contains any constraints a client should adhere to and provides additional metadata about a {@link io.ably.lib.realtime.Connection}, - * such as if a request to {@link io.ably.lib.realtime.Channel#publish} a message that exceeds the maximum message size should + * Contains any constraints a client should adhere to and provides additional metadata about a {@link io.ably.pubsub.realtime.Connection}, + * such as if a request to {@link io.ably.pubsub.realtime.Channel#publish} a message that exceeds the maximum message size should * be rejected immediately without communicating with Ably. */ public class ConnectionDetails { diff --git a/lib/src/main/java/io/ably/lib/types/DecodingContext.java b/lib/src/main/java/io/ably/pubsub/types/DecodingContext.java similarity index 96% rename from lib/src/main/java/io/ably/lib/types/DecodingContext.java rename to lib/src/main/java/io/ably/pubsub/types/DecodingContext.java index c8fe6f311..bc4f90a10 100644 --- a/lib/src/main/java/io/ably/lib/types/DecodingContext.java +++ b/lib/src/main/java/io/ably/pubsub/types/DecodingContext.java @@ -1,4 +1,4 @@ -package io.ably.lib.types; +package io.ably.pubsub.types; import java.nio.charset.Charset; diff --git a/lib/src/main/java/io/ably/lib/types/DeltaExtras.java b/lib/src/main/java/io/ably/pubsub/types/DeltaExtras.java similarity index 98% rename from lib/src/main/java/io/ably/lib/types/DeltaExtras.java rename to lib/src/main/java/io/ably/pubsub/types/DeltaExtras.java index 7388755cc..d62b83c14 100644 --- a/lib/src/main/java/io/ably/lib/types/DeltaExtras.java +++ b/lib/src/main/java/io/ably/pubsub/types/DeltaExtras.java @@ -1,4 +1,4 @@ -package io.ably.lib.types; +package io.ably.pubsub.types; import com.google.gson.JsonObject; import org.msgpack.value.Value; diff --git a/lib/src/main/java/io/ably/lib/types/ErrorInfo.java b/lib/src/main/java/io/ably/pubsub/types/ErrorInfo.java similarity index 98% rename from lib/src/main/java/io/ably/lib/types/ErrorInfo.java rename to lib/src/main/java/io/ably/pubsub/types/ErrorInfo.java index 2b9f9f147..b543cd264 100644 --- a/lib/src/main/java/io/ably/lib/types/ErrorInfo.java +++ b/lib/src/main/java/io/ably/pubsub/types/ErrorInfo.java @@ -1,10 +1,10 @@ -package io.ably.lib.types; +package io.ably.pubsub.types; -import io.ably.lib.util.Serialisation; +import io.ably.pubsub.util.Serialisation; import org.msgpack.core.MessageFormat; import org.msgpack.core.MessageUnpacker; -import io.ably.lib.util.Log; +import io.ably.pubsub.util.Log; import java.io.IOException; import java.net.NoRouteToHostException; diff --git a/lib/src/main/java/io/ably/lib/types/ErrorResponse.java b/lib/src/main/java/io/ably/pubsub/types/ErrorResponse.java similarity index 85% rename from lib/src/main/java/io/ably/lib/types/ErrorResponse.java rename to lib/src/main/java/io/ably/pubsub/types/ErrorResponse.java index 3b5c2299d..fe11e6eb8 100644 --- a/lib/src/main/java/io/ably/lib/types/ErrorResponse.java +++ b/lib/src/main/java/io/ably/pubsub/types/ErrorResponse.java @@ -1,6 +1,6 @@ -package io.ably.lib.types; +package io.ably.pubsub.types; -import io.ably.lib.util.Serialisation; +import io.ably.pubsub.util.Serialisation; public class ErrorResponse { public ErrorInfo error; diff --git a/lib/src/main/java/io/ably/lib/types/HttpPaginatedResponse.java b/lib/src/main/java/io/ably/pubsub/types/HttpPaginatedResponse.java similarity index 98% rename from lib/src/main/java/io/ably/lib/types/HttpPaginatedResponse.java rename to lib/src/main/java/io/ably/pubsub/types/HttpPaginatedResponse.java index 47ce89476..3ee68abc0 100644 --- a/lib/src/main/java/io/ably/lib/types/HttpPaginatedResponse.java +++ b/lib/src/main/java/io/ably/pubsub/types/HttpPaginatedResponse.java @@ -1,4 +1,4 @@ -package io.ably.lib.types; +package io.ably.pubsub.types; import com.google.gson.JsonElement; diff --git a/lib/src/main/java/io/ably/lib/types/Message.java b/lib/src/main/java/io/ably/pubsub/types/Message.java similarity index 99% rename from lib/src/main/java/io/ably/lib/types/Message.java rename to lib/src/main/java/io/ably/pubsub/types/Message.java index a232a6e55..f699202f9 100644 --- a/lib/src/main/java/io/ably/lib/types/Message.java +++ b/lib/src/main/java/io/ably/pubsub/types/Message.java @@ -1,4 +1,4 @@ -package io.ably.lib.types; +package io.ably.pubsub.types; import java.io.IOException; import java.lang.reflect.Type; @@ -12,12 +12,12 @@ import com.google.gson.JsonParseException; import com.google.gson.JsonSerializationContext; import com.google.gson.JsonSerializer; -import io.ably.lib.util.Serialisation; +import io.ably.pubsub.util.Serialisation; import org.msgpack.core.MessageFormat; import org.msgpack.core.MessagePacker; import org.msgpack.core.MessageUnpacker; -import io.ably.lib.util.Log; +import io.ably.pubsub.util.Log; /** * Contains an individual message that is sent to, or received from, Ably. @@ -230,7 +230,7 @@ Message readMsgpack(MessageUnpacker unpacker) throws IOException { } /** - * Sets the channel names and message contents to {@link io.ably.lib.realtime.AblyRealtime#publishBatch}. + * Sets the channel names and message contents to {@link io.ably.pubsub.realtime.PubSubRealtimeClient#publishBatch}. */ public static class Batch { /** diff --git a/lib/src/main/java/io/ably/lib/types/MessageAction.java b/lib/src/main/java/io/ably/pubsub/types/MessageAction.java similarity index 91% rename from lib/src/main/java/io/ably/lib/types/MessageAction.java rename to lib/src/main/java/io/ably/pubsub/types/MessageAction.java index 20b580233..20750e071 100644 --- a/lib/src/main/java/io/ably/lib/types/MessageAction.java +++ b/lib/src/main/java/io/ably/pubsub/types/MessageAction.java @@ -1,4 +1,4 @@ -package io.ably.lib.types; +package io.ably.pubsub.types; public enum MessageAction { MESSAGE_CREATE, // 0 diff --git a/lib/src/main/java/io/ably/lib/types/MessageAnnotations.java b/lib/src/main/java/io/ably/pubsub/types/MessageAnnotations.java similarity index 98% rename from lib/src/main/java/io/ably/lib/types/MessageAnnotations.java rename to lib/src/main/java/io/ably/pubsub/types/MessageAnnotations.java index a8d3b9bfb..4f7b526ab 100644 --- a/lib/src/main/java/io/ably/lib/types/MessageAnnotations.java +++ b/lib/src/main/java/io/ably/pubsub/types/MessageAnnotations.java @@ -1,4 +1,4 @@ -package io.ably.lib.types; +package io.ably.pubsub.types; import com.google.gson.JsonDeserializationContext; import com.google.gson.JsonDeserializer; @@ -7,7 +7,7 @@ import com.google.gson.JsonParseException; import com.google.gson.JsonSerializationContext; import com.google.gson.JsonSerializer; -import io.ably.lib.util.Log; +import io.ably.pubsub.util.Log; import org.msgpack.core.MessageFormat; import org.msgpack.core.MessagePacker; import org.msgpack.core.MessageUnpacker; diff --git a/lib/src/main/java/io/ably/lib/types/MessageDecodeException.java b/lib/src/main/java/io/ably/pubsub/types/MessageDecodeException.java similarity index 95% rename from lib/src/main/java/io/ably/lib/types/MessageDecodeException.java rename to lib/src/main/java/io/ably/pubsub/types/MessageDecodeException.java index 3c4043201..8548ac814 100644 --- a/lib/src/main/java/io/ably/lib/types/MessageDecodeException.java +++ b/lib/src/main/java/io/ably/pubsub/types/MessageDecodeException.java @@ -1,4 +1,4 @@ -package io.ably.lib.types; +package io.ably.pubsub.types; /** * Special AblyException for message decoding problems diff --git a/lib/src/main/java/io/ably/lib/types/MessageExtras.java b/lib/src/main/java/io/ably/pubsub/types/MessageExtras.java similarity index 98% rename from lib/src/main/java/io/ably/lib/types/MessageExtras.java rename to lib/src/main/java/io/ably/pubsub/types/MessageExtras.java index d3da9a92d..7e3d5db41 100644 --- a/lib/src/main/java/io/ably/lib/types/MessageExtras.java +++ b/lib/src/main/java/io/ably/pubsub/types/MessageExtras.java @@ -1,10 +1,10 @@ -package io.ably.lib.types; +package io.ably.pubsub.types; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonSerializationContext; import com.google.gson.JsonSerializer; -import io.ably.lib.util.Serialisation; +import io.ably.pubsub.util.Serialisation; import org.msgpack.core.MessagePacker; import org.msgpack.core.MessageUnpacker; import org.msgpack.value.ImmutableMapValue; diff --git a/lib/src/main/java/io/ably/lib/types/MessageOperation.java b/lib/src/main/java/io/ably/pubsub/types/MessageOperation.java similarity index 97% rename from lib/src/main/java/io/ably/lib/types/MessageOperation.java rename to lib/src/main/java/io/ably/pubsub/types/MessageOperation.java index ecb16f3e6..0b806c769 100644 --- a/lib/src/main/java/io/ably/lib/types/MessageOperation.java +++ b/lib/src/main/java/io/ably/pubsub/types/MessageOperation.java @@ -1,7 +1,7 @@ -package io.ably.lib.types; +package io.ably.pubsub.types; import com.google.gson.JsonObject; -import io.ably.lib.util.Serialisation; +import io.ably.pubsub.util.Serialisation; import org.msgpack.core.MessagePacker; import java.io.IOException; diff --git a/lib/src/main/java/io/ably/lib/types/MessageSerializer.java b/lib/src/main/java/io/ably/pubsub/types/MessageSerializer.java similarity index 98% rename from lib/src/main/java/io/ably/lib/types/MessageSerializer.java rename to lib/src/main/java/io/ably/pubsub/types/MessageSerializer.java index b53c98110..c6edfd8d8 100644 --- a/lib/src/main/java/io/ably/lib/types/MessageSerializer.java +++ b/lib/src/main/java/io/ably/pubsub/types/MessageSerializer.java @@ -1,19 +1,19 @@ -package io.ably.lib.types; +package io.ably.pubsub.types; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.HashMap; import java.util.Map; -import io.ably.lib.http.HttpCore; -import io.ably.lib.http.HttpUtils; -import io.ably.lib.util.Log; +import io.ably.pubsub.http.HttpCore; +import io.ably.pubsub.http.HttpUtils; +import io.ably.pubsub.util.Log; import org.msgpack.core.MessageFormat; import org.msgpack.core.MessagePacker; import org.msgpack.core.MessageUnpacker; -import io.ably.lib.util.Serialisation; +import io.ably.pubsub.util.Serialisation; /** * MessageReader: internal diff --git a/lib/src/main/java/io/ably/lib/types/MessageVersion.java b/lib/src/main/java/io/ably/pubsub/types/MessageVersion.java similarity index 99% rename from lib/src/main/java/io/ably/lib/types/MessageVersion.java rename to lib/src/main/java/io/ably/pubsub/types/MessageVersion.java index d98603779..a107f4ddb 100644 --- a/lib/src/main/java/io/ably/lib/types/MessageVersion.java +++ b/lib/src/main/java/io/ably/pubsub/types/MessageVersion.java @@ -1,4 +1,4 @@ -package io.ably.lib.types; +package io.ably.pubsub.types; import com.google.gson.JsonDeserializationContext; import com.google.gson.JsonDeserializer; @@ -7,7 +7,7 @@ import com.google.gson.JsonParseException; import com.google.gson.JsonSerializationContext; import com.google.gson.JsonSerializer; -import io.ably.lib.util.Log; +import io.ably.pubsub.util.Log; import org.jetbrains.annotations.NotNull; import org.msgpack.core.MessageFormat; import org.msgpack.core.MessagePacker; diff --git a/lib/src/main/java/io/ably/lib/types/NonRetriableTokenException.java b/lib/src/main/java/io/ably/pubsub/types/NonRetriableTokenException.java similarity index 84% rename from lib/src/main/java/io/ably/lib/types/NonRetriableTokenException.java rename to lib/src/main/java/io/ably/pubsub/types/NonRetriableTokenException.java index 14a9e3c7f..f9242f522 100644 --- a/lib/src/main/java/io/ably/lib/types/NonRetriableTokenException.java +++ b/lib/src/main/java/io/ably/pubsub/types/NonRetriableTokenException.java @@ -1,4 +1,4 @@ -package io.ably.lib.types; +package io.ably.pubsub.types; /** * Implement this marker interface in your exception class if the token auth operation should not be retried. diff --git a/lib/src/main/java/io/ably/lib/types/PaginatedResult.java b/lib/src/main/java/io/ably/pubsub/types/PaginatedResult.java similarity index 98% rename from lib/src/main/java/io/ably/lib/types/PaginatedResult.java rename to lib/src/main/java/io/ably/pubsub/types/PaginatedResult.java index e606d2712..e3a6b17e2 100644 --- a/lib/src/main/java/io/ably/lib/types/PaginatedResult.java +++ b/lib/src/main/java/io/ably/pubsub/types/PaginatedResult.java @@ -1,4 +1,4 @@ -package io.ably.lib.types; +package io.ably.pubsub.types; /** * Contains a page of results for message or presence history, stats, or REST presence requests. diff --git a/lib/src/main/java/io/ably/lib/types/Param.java b/lib/src/main/java/io/ably/pubsub/types/Param.java similarity index 98% rename from lib/src/main/java/io/ably/lib/types/Param.java rename to lib/src/main/java/io/ably/pubsub/types/Param.java index 8a2e85365..458dbd158 100644 --- a/lib/src/main/java/io/ably/lib/types/Param.java +++ b/lib/src/main/java/io/ably/pubsub/types/Param.java @@ -1,4 +1,4 @@ -package io.ably.lib.types; +package io.ably.pubsub.types; /** * A class encapsulating a key/value pair diff --git a/lib/src/main/java/io/ably/lib/types/PresenceMessage.java b/lib/src/main/java/io/ably/pubsub/types/PresenceMessage.java similarity index 99% rename from lib/src/main/java/io/ably/lib/types/PresenceMessage.java rename to lib/src/main/java/io/ably/pubsub/types/PresenceMessage.java index d3073a879..2c1bc2936 100644 --- a/lib/src/main/java/io/ably/lib/types/PresenceMessage.java +++ b/lib/src/main/java/io/ably/pubsub/types/PresenceMessage.java @@ -1,4 +1,4 @@ -package io.ably.lib.types; +package io.ably.pubsub.types; import java.io.IOException; import java.lang.reflect.Type; @@ -10,12 +10,12 @@ import com.google.gson.JsonParseException; import com.google.gson.JsonSerializationContext; import com.google.gson.JsonSerializer; -import io.ably.lib.util.Serialisation; +import io.ably.pubsub.util.Serialisation; import org.msgpack.core.MessageFormat; import org.msgpack.core.MessagePacker; import org.msgpack.core.MessageUnpacker; -import io.ably.lib.util.Log; +import io.ably.pubsub.util.Log; /** * A class representing an individual presence update to be sent or received diff --git a/lib/src/main/java/io/ably/lib/types/PresenceSerializer.java b/lib/src/main/java/io/ably/pubsub/types/PresenceSerializer.java similarity index 96% rename from lib/src/main/java/io/ably/lib/types/PresenceSerializer.java rename to lib/src/main/java/io/ably/pubsub/types/PresenceSerializer.java index 9919010e0..30d3dc079 100644 --- a/lib/src/main/java/io/ably/lib/types/PresenceSerializer.java +++ b/lib/src/main/java/io/ably/pubsub/types/PresenceSerializer.java @@ -1,15 +1,15 @@ -package io.ably.lib.types; +package io.ably.pubsub.types; import java.io.ByteArrayOutputStream; import java.io.IOException; -import io.ably.lib.http.HttpCore; -import io.ably.lib.http.HttpUtils; -import io.ably.lib.util.Log; +import io.ably.pubsub.http.HttpCore; +import io.ably.pubsub.http.HttpUtils; +import io.ably.pubsub.util.Log; import org.msgpack.core.MessagePacker; import org.msgpack.core.MessageUnpacker; -import io.ably.lib.util.Serialisation; +import io.ably.pubsub.util.Serialisation; /** * PresenceSerializer: internal diff --git a/lib/src/main/java/io/ably/lib/types/ProtocolMessage.java b/lib/src/main/java/io/ably/pubsub/types/ProtocolMessage.java similarity index 98% rename from lib/src/main/java/io/ably/lib/types/ProtocolMessage.java rename to lib/src/main/java/io/ably/pubsub/types/ProtocolMessage.java index bab089c6e..48c1c5138 100644 --- a/lib/src/main/java/io/ably/lib/types/ProtocolMessage.java +++ b/lib/src/main/java/io/ably/pubsub/types/ProtocolMessage.java @@ -1,12 +1,12 @@ -package io.ably.lib.types; +package io.ably.pubsub.types; import java.io.IOException; import java.lang.reflect.Type; import java.util.Map; import com.google.gson.annotations.JsonAdapter; -import io.ably.lib.liveobjects.serialization.ObjectJsonSerializer; -import io.ably.lib.liveobjects.serialization.ObjectSerializer; +import io.ably.pubsub.liveobjects.serialization.ObjectJsonSerializer; +import io.ably.pubsub.liveobjects.serialization.ObjectSerializer; import org.jetbrains.annotations.Nullable; import org.msgpack.core.MessageFormat; import org.msgpack.core.MessagePacker; @@ -20,7 +20,7 @@ import com.google.gson.JsonSerializationContext; import com.google.gson.JsonSerializer; -import io.ably.lib.util.Log; +import io.ably.pubsub.util.Log; /** * A message sent and received over the Realtime protocol. diff --git a/lib/src/main/java/io/ably/lib/types/ProtocolSerializer.java b/lib/src/main/java/io/ably/pubsub/types/ProtocolSerializer.java similarity index 96% rename from lib/src/main/java/io/ably/lib/types/ProtocolSerializer.java rename to lib/src/main/java/io/ably/pubsub/types/ProtocolSerializer.java index e33bfe186..aa5ff9485 100644 --- a/lib/src/main/java/io/ably/lib/types/ProtocolSerializer.java +++ b/lib/src/main/java/io/ably/pubsub/types/ProtocolSerializer.java @@ -1,4 +1,4 @@ -package io.ably.lib.types; +package io.ably.pubsub.types; import java.io.ByteArrayOutputStream; import java.io.IOException; @@ -7,7 +7,7 @@ import org.msgpack.core.MessagePacker; import org.msgpack.core.MessageUnpacker; -import io.ably.lib.util.Serialisation; +import io.ably.pubsub.util.Serialisation; public class ProtocolSerializer { diff --git a/lib/src/main/java/io/ably/lib/types/ProxyOptions.java b/lib/src/main/java/io/ably/pubsub/types/ProxyOptions.java similarity index 77% rename from lib/src/main/java/io/ably/lib/types/ProxyOptions.java rename to lib/src/main/java/io/ably/pubsub/types/ProxyOptions.java index 11465f8c1..985e7f3de 100644 --- a/lib/src/main/java/io/ably/lib/types/ProxyOptions.java +++ b/lib/src/main/java/io/ably/pubsub/types/ProxyOptions.java @@ -1,6 +1,6 @@ -package io.ably.lib.types; +package io.ably.pubsub.types; -import io.ably.lib.http.HttpAuth; +import io.ably.pubsub.http.HttpAuth; public class ProxyOptions { public String host; diff --git a/lib/src/main/java/io/ably/lib/types/PublishResponse.java b/lib/src/main/java/io/ably/pubsub/types/PublishResponse.java similarity index 98% rename from lib/src/main/java/io/ably/lib/types/PublishResponse.java rename to lib/src/main/java/io/ably/pubsub/types/PublishResponse.java index b0a80e6ed..0288546b3 100644 --- a/lib/src/main/java/io/ably/lib/types/PublishResponse.java +++ b/lib/src/main/java/io/ably/pubsub/types/PublishResponse.java @@ -1,9 +1,9 @@ -package io.ably.lib.types; +package io.ably.pubsub.types; import com.google.gson.annotations.SerializedName; -import io.ably.lib.http.HttpCore; -import io.ably.lib.util.Log; -import io.ably.lib.util.Serialisation; +import io.ably.pubsub.http.HttpCore; +import io.ably.pubsub.util.Log; +import io.ably.pubsub.util.Serialisation; import org.msgpack.core.MessageFormat; import org.msgpack.core.MessageUnpacker; diff --git a/lib/src/main/java/io/ably/lib/types/PublishResult.java b/lib/src/main/java/io/ably/pubsub/types/PublishResult.java similarity index 97% rename from lib/src/main/java/io/ably/lib/types/PublishResult.java rename to lib/src/main/java/io/ably/pubsub/types/PublishResult.java index d9c3091e1..ae5f8d49b 100644 --- a/lib/src/main/java/io/ably/lib/types/PublishResult.java +++ b/lib/src/main/java/io/ably/pubsub/types/PublishResult.java @@ -1,7 +1,7 @@ -package io.ably.lib.types; +package io.ably.pubsub.types; -import io.ably.lib.http.HttpCore; -import io.ably.lib.util.Serialisation; +import io.ably.pubsub.http.HttpCore; +import io.ably.pubsub.util.Serialisation; import org.jetbrains.annotations.Nullable; import org.msgpack.core.MessageFormat; import org.msgpack.core.MessagePacker; diff --git a/lib/src/main/java/io/ably/lib/types/ReadOnlyMap.java b/lib/src/main/java/io/ably/pubsub/types/ReadOnlyMap.java similarity index 96% rename from lib/src/main/java/io/ably/lib/types/ReadOnlyMap.java rename to lib/src/main/java/io/ably/pubsub/types/ReadOnlyMap.java index 30be1f66f..e207dae9a 100644 --- a/lib/src/main/java/io/ably/lib/types/ReadOnlyMap.java +++ b/lib/src/main/java/io/ably/pubsub/types/ReadOnlyMap.java @@ -1,4 +1,4 @@ -package io.ably.lib.types; +package io.ably.pubsub.types; import java.util.Map; diff --git a/lib/src/main/java/io/ably/lib/types/RecoveryKeyContext.java b/lib/src/main/java/io/ably/pubsub/types/RecoveryKeyContext.java similarity index 92% rename from lib/src/main/java/io/ably/lib/types/RecoveryKeyContext.java rename to lib/src/main/java/io/ably/pubsub/types/RecoveryKeyContext.java index 9ccd005a4..356df7a34 100644 --- a/lib/src/main/java/io/ably/lib/types/RecoveryKeyContext.java +++ b/lib/src/main/java/io/ably/pubsub/types/RecoveryKeyContext.java @@ -1,12 +1,12 @@ -package io.ably.lib.types; +package io.ably.pubsub.types; import com.google.gson.JsonSyntaxException; import java.util.Map; import java.util.TreeMap; -import io.ably.lib.util.Log; -import io.ably.lib.util.Serialisation; +import io.ably.pubsub.util.Log; +import io.ably.pubsub.util.Serialisation; public class RecoveryKeyContext { private static final String TAG = "RecoveryKeyContext"; diff --git a/lib/src/main/java/io/ably/lib/types/Stats.java b/lib/src/main/java/io/ably/pubsub/types/Stats.java similarity index 99% rename from lib/src/main/java/io/ably/lib/types/Stats.java rename to lib/src/main/java/io/ably/pubsub/types/Stats.java index ad65f24af..7a2550a94 100644 --- a/lib/src/main/java/io/ably/lib/types/Stats.java +++ b/lib/src/main/java/io/ably/pubsub/types/Stats.java @@ -1,4 +1,4 @@ -package io.ably.lib.types; +package io.ably.pubsub.types; import java.text.ParseException; import java.text.SimpleDateFormat; diff --git a/lib/src/main/java/io/ably/lib/types/StatsReader.java b/lib/src/main/java/io/ably/pubsub/types/StatsReader.java similarity index 89% rename from lib/src/main/java/io/ably/lib/types/StatsReader.java rename to lib/src/main/java/io/ably/pubsub/types/StatsReader.java index 21456b3e1..4bb75e7f4 100644 --- a/lib/src/main/java/io/ably/lib/types/StatsReader.java +++ b/lib/src/main/java/io/ably/pubsub/types/StatsReader.java @@ -1,9 +1,9 @@ -package io.ably.lib.types; +package io.ably.pubsub.types; import java.io.UnsupportedEncodingException; -import io.ably.lib.http.HttpCore; -import io.ably.lib.util.Serialisation; +import io.ably.pubsub.http.HttpCore; +import io.ably.pubsub.util.Serialisation; /** * StatsReader: internal diff --git a/lib/src/main/java/io/ably/lib/types/Summary.java b/lib/src/main/java/io/ably/pubsub/types/Summary.java similarity index 98% rename from lib/src/main/java/io/ably/lib/types/Summary.java rename to lib/src/main/java/io/ably/pubsub/types/Summary.java index f461be681..28cfe4578 100644 --- a/lib/src/main/java/io/ably/lib/types/Summary.java +++ b/lib/src/main/java/io/ably/pubsub/types/Summary.java @@ -1,4 +1,4 @@ -package io.ably.lib.types; +package io.ably.pubsub.types; import com.google.gson.JsonDeserializationContext; import com.google.gson.JsonDeserializer; @@ -7,8 +7,8 @@ import com.google.gson.JsonParseException; import com.google.gson.JsonSerializationContext; import com.google.gson.JsonSerializer; -import io.ably.lib.util.Log; -import io.ably.lib.util.Serialisation; +import io.ably.pubsub.util.Log; +import io.ably.pubsub.util.Serialisation; import org.msgpack.core.MessagePacker; import org.msgpack.core.MessageUnpacker; diff --git a/lib/src/main/java/io/ably/lib/types/SummaryClientIdCounts.java b/lib/src/main/java/io/ably/pubsub/types/SummaryClientIdCounts.java similarity index 97% rename from lib/src/main/java/io/ably/lib/types/SummaryClientIdCounts.java rename to lib/src/main/java/io/ably/pubsub/types/SummaryClientIdCounts.java index 574746575..32a5a4b70 100644 --- a/lib/src/main/java/io/ably/lib/types/SummaryClientIdCounts.java +++ b/lib/src/main/java/io/ably/pubsub/types/SummaryClientIdCounts.java @@ -1,4 +1,4 @@ -package io.ably.lib.types; +package io.ably.pubsub.types; import java.util.Map; diff --git a/lib/src/main/java/io/ably/lib/types/SummaryClientIdList.java b/lib/src/main/java/io/ably/pubsub/types/SummaryClientIdList.java similarity index 96% rename from lib/src/main/java/io/ably/lib/types/SummaryClientIdList.java rename to lib/src/main/java/io/ably/pubsub/types/SummaryClientIdList.java index 7563d34a2..5d387eea6 100644 --- a/lib/src/main/java/io/ably/lib/types/SummaryClientIdList.java +++ b/lib/src/main/java/io/ably/pubsub/types/SummaryClientIdList.java @@ -1,4 +1,4 @@ -package io.ably.lib.types; +package io.ably.pubsub.types; import java.util.List; diff --git a/lib/src/main/java/io/ably/lib/types/SummaryTotal.java b/lib/src/main/java/io/ably/pubsub/types/SummaryTotal.java similarity index 81% rename from lib/src/main/java/io/ably/lib/types/SummaryTotal.java rename to lib/src/main/java/io/ably/pubsub/types/SummaryTotal.java index f7d4b0724..bd9eefc80 100644 --- a/lib/src/main/java/io/ably/lib/types/SummaryTotal.java +++ b/lib/src/main/java/io/ably/pubsub/types/SummaryTotal.java @@ -1,4 +1,4 @@ -package io.ably.lib.types; +package io.ably.pubsub.types; public class SummaryTotal { public final int total; // TM7e1a diff --git a/lib/src/main/java/io/ably/lib/types/UpdateDeleteResult.java b/lib/src/main/java/io/ably/pubsub/types/UpdateDeleteResult.java similarity index 96% rename from lib/src/main/java/io/ably/lib/types/UpdateDeleteResult.java rename to lib/src/main/java/io/ably/pubsub/types/UpdateDeleteResult.java index 97fe51628..93d584b94 100644 --- a/lib/src/main/java/io/ably/lib/types/UpdateDeleteResult.java +++ b/lib/src/main/java/io/ably/pubsub/types/UpdateDeleteResult.java @@ -1,7 +1,7 @@ -package io.ably.lib.types; +package io.ably.pubsub.types; -import io.ably.lib.http.HttpCore; -import io.ably.lib.util.Serialisation; +import io.ably.pubsub.http.HttpCore; +import io.ably.pubsub.util.Serialisation; import org.jetbrains.annotations.Nullable; import org.msgpack.core.MessageFormat; import org.msgpack.core.MessageUnpacker; diff --git a/lib/src/main/java/io/ably/lib/util/AblyTimer.java b/lib/src/main/java/io/ably/pubsub/util/AblyTimer.java similarity index 82% rename from lib/src/main/java/io/ably/lib/util/AblyTimer.java rename to lib/src/main/java/io/ably/pubsub/util/AblyTimer.java index 74df5ccb3..c6f9e1b5c 100644 --- a/lib/src/main/java/io/ably/lib/util/AblyTimer.java +++ b/lib/src/main/java/io/ably/pubsub/util/AblyTimer.java @@ -1,4 +1,4 @@ -package io.ably.lib.util; +package io.ably.pubsub.util; import java.util.TimerTask; diff --git a/lib/src/main/java/io/ably/lib/util/AgentHeaderCreator.java b/lib/src/main/java/io/ably/pubsub/util/AgentHeaderCreator.java similarity index 96% rename from lib/src/main/java/io/ably/lib/util/AgentHeaderCreator.java rename to lib/src/main/java/io/ably/pubsub/util/AgentHeaderCreator.java index 8999e94f5..daaaff38e 100644 --- a/lib/src/main/java/io/ably/lib/util/AgentHeaderCreator.java +++ b/lib/src/main/java/io/ably/pubsub/util/AgentHeaderCreator.java @@ -1,6 +1,6 @@ -package io.ably.lib.util; +package io.ably.pubsub.util; -import io.ably.lib.transport.Defaults; +import io.ably.pubsub.transport.Defaults; import java.util.Map; diff --git a/lib/src/main/java/io/ably/lib/util/Base64Coder.java b/lib/src/main/java/io/ably/pubsub/util/Base64Coder.java similarity index 99% rename from lib/src/main/java/io/ably/lib/util/Base64Coder.java rename to lib/src/main/java/io/ably/pubsub/util/Base64Coder.java index 9a68562c2..00c2fe9e9 100644 --- a/lib/src/main/java/io/ably/lib/util/Base64Coder.java +++ b/lib/src/main/java/io/ably/pubsub/util/Base64Coder.java @@ -1,4 +1,4 @@ -package io.ably.lib.util; +package io.ably.pubsub.util; import java.nio.charset.Charset; diff --git a/lib/src/main/java/io/ably/lib/util/ClientOptionsUtils.java b/lib/src/main/java/io/ably/pubsub/util/ClientOptionsUtils.java similarity index 85% rename from lib/src/main/java/io/ably/lib/util/ClientOptionsUtils.java rename to lib/src/main/java/io/ably/pubsub/util/ClientOptionsUtils.java index 1fd3d02ce..c9387d3fc 100644 --- a/lib/src/main/java/io/ably/lib/util/ClientOptionsUtils.java +++ b/lib/src/main/java/io/ably/pubsub/util/ClientOptionsUtils.java @@ -1,8 +1,8 @@ -package io.ably.lib.util; +package io.ably.pubsub.util; -import io.ably.lib.network.ProxyAuthType; -import io.ably.lib.network.ProxyConfig; -import io.ably.lib.types.ClientOptions; +import io.ably.pubsub.network.ProxyAuthType; +import io.ably.pubsub.network.ProxyConfig; +import io.ably.pubsub.types.ClientOptions; import java.util.Arrays; diff --git a/lib/src/main/java/io/ably/lib/util/Clock.java b/lib/src/main/java/io/ably/pubsub/util/Clock.java similarity index 96% rename from lib/src/main/java/io/ably/lib/util/Clock.java rename to lib/src/main/java/io/ably/pubsub/util/Clock.java index d7f64d2e7..c6fde146d 100644 --- a/lib/src/main/java/io/ably/lib/util/Clock.java +++ b/lib/src/main/java/io/ably/pubsub/util/Clock.java @@ -1,11 +1,11 @@ -package io.ably.lib.util; +package io.ably.pubsub.util; /** * Abstraction over time-related operations used throughout the SDK. * *

The default implementation, {@link SystemClock}, delegates to the real system clock and * standard Java concurrency primitives. Tests and debug builds can supply an alternative - * implementation (e.g. a fake/controllable clock) via {@link io.ably.lib.debug.DebugOptions#clock} + * implementation (e.g. a fake/controllable clock) via {@link io.ably.pubsub.debug.DebugOptions#clock} * to drive time-dependent behaviour deterministically without sleeping. */ public interface Clock { diff --git a/lib/src/main/java/io/ably/lib/util/CollectionUtils.java b/lib/src/main/java/io/ably/pubsub/util/CollectionUtils.java similarity index 94% rename from lib/src/main/java/io/ably/lib/util/CollectionUtils.java rename to lib/src/main/java/io/ably/pubsub/util/CollectionUtils.java index fe91ca934..ff8e57946 100644 --- a/lib/src/main/java/io/ably/lib/util/CollectionUtils.java +++ b/lib/src/main/java/io/ably/pubsub/util/CollectionUtils.java @@ -1,4 +1,4 @@ -package io.ably.lib.util; +package io.ably.pubsub.util; import java.util.HashMap; import java.util.Map; diff --git a/lib/src/main/java/io/ably/lib/util/Crypto.java b/lib/src/main/java/io/ably/pubsub/util/Crypto.java similarity index 98% rename from lib/src/main/java/io/ably/lib/util/Crypto.java rename to lib/src/main/java/io/ably/pubsub/util/Crypto.java index 083de03ea..15609bed5 100644 --- a/lib/src/main/java/io/ably/lib/util/Crypto.java +++ b/lib/src/main/java/io/ably/pubsub/util/Crypto.java @@ -1,4 +1,4 @@ -package io.ably.lib.util; +package io.ably.pubsub.util; import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; @@ -15,12 +15,12 @@ import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; -import io.ably.lib.types.AblyException; -import io.ably.lib.types.ErrorInfo; -import io.ably.lib.types.Param; +import io.ably.pubsub.types.AblyException; +import io.ably.pubsub.types.ErrorInfo; +import io.ably.pubsub.types.Param; /** - * Contains the properties required to configure the encryption of {@link io.ably.lib.types.Message} payloads. + * Contains the properties required to configure the encryption of {@link io.ably.pubsub.types.Message} payloads. */ public class Crypto { @@ -29,7 +29,7 @@ public class Crypto { public static final int DEFAULT_BLOCKLENGTH = 16; // bytes /** - * Sets the properties to configure encryption for a {@link io.ably.lib.rest.Channel} or {@link io.ably.lib.realtime.Channel} object. + * Sets the properties to configure encryption for a {@link io.ably.pubsub.http.Channel} or {@link io.ably.pubsub.realtime.Channel} object. */ public static class CipherParams { /** diff --git a/lib/src/main/java/io/ably/lib/util/CurrentThreadExecutor.java b/lib/src/main/java/io/ably/pubsub/util/CurrentThreadExecutor.java similarity index 81% rename from lib/src/main/java/io/ably/lib/util/CurrentThreadExecutor.java rename to lib/src/main/java/io/ably/pubsub/util/CurrentThreadExecutor.java index 8a5ba481d..4175fb01f 100644 --- a/lib/src/main/java/io/ably/lib/util/CurrentThreadExecutor.java +++ b/lib/src/main/java/io/ably/pubsub/util/CurrentThreadExecutor.java @@ -1,6 +1,6 @@ -package io.ably.lib.util; +package io.ably.pubsub.util; -import io.ably.lib.http.CloseableExecutor; +import io.ably.pubsub.http.CloseableExecutor; public class CurrentThreadExecutor implements CloseableExecutor { public static CurrentThreadExecutor INSTANCE = new CurrentThreadExecutor(); diff --git a/lib/src/main/java/io/ably/lib/util/EventEmitter.java b/lib/src/main/java/io/ably/pubsub/util/EventEmitter.java similarity index 97% rename from lib/src/main/java/io/ably/lib/util/EventEmitter.java rename to lib/src/main/java/io/ably/pubsub/util/EventEmitter.java index 74d59b833..83e29bfb7 100644 --- a/lib/src/main/java/io/ably/lib/util/EventEmitter.java +++ b/lib/src/main/java/io/ably/pubsub/util/EventEmitter.java @@ -1,4 +1,4 @@ -package io.ably.lib.util; +package io.ably.pubsub.util; import java.util.ArrayList; import java.util.HashMap; @@ -8,7 +8,7 @@ /** * A generic interface for event registration and delivery used in a number of the types in the Realtime client library. - * For example, the {@link io.ably.lib.realtime.Connection} object emits events for connection state using the EventEmitter pattern. + * For example, the {@link io.ably.pubsub.realtime.Connection} object emits events for connection state using the EventEmitter pattern. * * @param an Enum containing the event names that listeners may be registered for * @param the interface type of the listener diff --git a/lib/src/main/java/io/ably/lib/util/InternalMap.java b/lib/src/main/java/io/ably/pubsub/util/InternalMap.java similarity index 95% rename from lib/src/main/java/io/ably/lib/util/InternalMap.java rename to lib/src/main/java/io/ably/pubsub/util/InternalMap.java index d732e9b40..bc8b75e55 100644 --- a/lib/src/main/java/io/ably/lib/util/InternalMap.java +++ b/lib/src/main/java/io/ably/pubsub/util/InternalMap.java @@ -1,10 +1,10 @@ -package io.ably.lib.util; +package io.ably.pubsub.util; import java.util.Map.Entry; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; -import io.ably.lib.types.ReadOnlyMap; +import io.ably.pubsub.types.ReadOnlyMap; /** * A map implemented using a {@link ConcurrentHashMap}. This class is a base class for other classes diff --git a/lib/src/main/java/io/ably/lib/util/JsonUtils.java b/lib/src/main/java/io/ably/pubsub/util/JsonUtils.java similarity index 97% rename from lib/src/main/java/io/ably/lib/util/JsonUtils.java rename to lib/src/main/java/io/ably/pubsub/util/JsonUtils.java index 5f028ecb4..7bed51c0a 100644 --- a/lib/src/main/java/io/ably/lib/util/JsonUtils.java +++ b/lib/src/main/java/io/ably/pubsub/util/JsonUtils.java @@ -1,4 +1,4 @@ -package io.ably.lib.util; +package io.ably.pubsub.util; import com.google.gson.JsonElement; import com.google.gson.JsonObject; diff --git a/lib/src/main/java/io/ably/lib/util/Listeners.java b/lib/src/main/java/io/ably/pubsub/util/Listeners.java similarity index 89% rename from lib/src/main/java/io/ably/lib/util/Listeners.java rename to lib/src/main/java/io/ably/pubsub/util/Listeners.java index 36076bee3..3b1da96b7 100644 --- a/lib/src/main/java/io/ably/lib/util/Listeners.java +++ b/lib/src/main/java/io/ably/pubsub/util/Listeners.java @@ -1,10 +1,10 @@ -package io.ably.lib.util; +package io.ably.pubsub.util; -import io.ably.lib.realtime.CompletionListener; -import io.ably.lib.types.Callback; -import io.ably.lib.types.ErrorInfo; -import io.ably.lib.types.PublishResult; -import io.ably.lib.types.UpdateDeleteResult; +import io.ably.pubsub.realtime.CompletionListener; +import io.ably.pubsub.types.Callback; +import io.ably.pubsub.types.ErrorInfo; +import io.ably.pubsub.types.PublishResult; +import io.ably.pubsub.types.UpdateDeleteResult; public class Listeners { diff --git a/lib/src/main/java/io/ably/lib/util/Log.java b/lib/src/main/java/io/ably/pubsub/util/Log.java similarity index 99% rename from lib/src/main/java/io/ably/lib/util/Log.java rename to lib/src/main/java/io/ably/pubsub/util/Log.java index ecd673ed2..f4e5fec5d 100644 --- a/lib/src/main/java/io/ably/lib/util/Log.java +++ b/lib/src/main/java/io/ably/pubsub/util/Log.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package io.ably.lib.util; +package io.ably.pubsub.util; import java.io.PrintStream; diff --git a/lib/src/main/java/io/ably/lib/util/Multicaster.java b/lib/src/main/java/io/ably/pubsub/util/Multicaster.java similarity index 97% rename from lib/src/main/java/io/ably/lib/util/Multicaster.java rename to lib/src/main/java/io/ably/pubsub/util/Multicaster.java index 9cd3f713f..150e01062 100644 --- a/lib/src/main/java/io/ably/lib/util/Multicaster.java +++ b/lib/src/main/java/io/ably/pubsub/util/Multicaster.java @@ -1,4 +1,4 @@ -package io.ably.lib.util; +package io.ably.pubsub.util; import java.util.ArrayList; import java.util.List; diff --git a/lib/src/main/java/io/ably/lib/util/ParamsUtils.java b/lib/src/main/java/io/ably/pubsub/util/ParamsUtils.java similarity index 86% rename from lib/src/main/java/io/ably/lib/util/ParamsUtils.java rename to lib/src/main/java/io/ably/pubsub/util/ParamsUtils.java index a89a74ecf..413ed6ca1 100644 --- a/lib/src/main/java/io/ably/lib/util/ParamsUtils.java +++ b/lib/src/main/java/io/ably/pubsub/util/ParamsUtils.java @@ -1,7 +1,7 @@ -package io.ably.lib.util; +package io.ably.pubsub.util; -import io.ably.lib.types.ClientOptions; -import io.ably.lib.types.Param; +import io.ably.pubsub.types.ClientOptions; +import io.ably.pubsub.types.Param; public class ParamsUtils { diff --git a/lib/src/main/java/io/ably/lib/util/PlatformAgentProvider.java b/lib/src/main/java/io/ably/pubsub/util/PlatformAgentProvider.java similarity index 89% rename from lib/src/main/java/io/ably/lib/util/PlatformAgentProvider.java rename to lib/src/main/java/io/ably/pubsub/util/PlatformAgentProvider.java index 5a082040c..923df395f 100644 --- a/lib/src/main/java/io/ably/lib/util/PlatformAgentProvider.java +++ b/lib/src/main/java/io/ably/pubsub/util/PlatformAgentProvider.java @@ -1,4 +1,4 @@ -package io.ably.lib.util; +package io.ably.pubsub.util; public interface PlatformAgentProvider { /** diff --git a/lib/src/main/java/io/ably/lib/util/ReconnectionStrategy.java b/lib/src/main/java/io/ably/pubsub/util/ReconnectionStrategy.java similarity index 97% rename from lib/src/main/java/io/ably/lib/util/ReconnectionStrategy.java rename to lib/src/main/java/io/ably/pubsub/util/ReconnectionStrategy.java index 581b7c9e4..71e0c2546 100644 --- a/lib/src/main/java/io/ably/lib/util/ReconnectionStrategy.java +++ b/lib/src/main/java/io/ably/pubsub/util/ReconnectionStrategy.java @@ -1,4 +1,4 @@ -package io.ably.lib.util; +package io.ably.pubsub.util; public class ReconnectionStrategy { diff --git a/lib/src/main/java/io/ably/lib/util/Serialisation.java b/lib/src/main/java/io/ably/pubsub/util/Serialisation.java similarity index 95% rename from lib/src/main/java/io/ably/lib/util/Serialisation.java rename to lib/src/main/java/io/ably/pubsub/util/Serialisation.java index caf1237bd..3467e9d20 100644 --- a/lib/src/main/java/io/ably/lib/util/Serialisation.java +++ b/lib/src/main/java/io/ably/pubsub/util/Serialisation.java @@ -1,4 +1,4 @@ -package io.ably.lib.util; +package io.ably.pubsub.util; import com.google.gson.Gson; import com.google.gson.GsonBuilder; @@ -8,19 +8,19 @@ import com.google.gson.JsonObject; import com.google.gson.JsonParser; import com.google.gson.JsonPrimitive; -import io.ably.lib.http.HttpCore; -import io.ably.lib.platform.Platform; -import io.ably.lib.types.AblyException; -import io.ably.lib.types.Annotation; -import io.ably.lib.types.AnnotationAction; -import io.ably.lib.types.ErrorInfo; -import io.ably.lib.types.Message; -import io.ably.lib.types.MessageAnnotations; -import io.ably.lib.types.MessageExtras; -import io.ably.lib.types.MessageVersion; -import io.ably.lib.types.PresenceMessage; -import io.ably.lib.types.ProtocolMessage; -import io.ably.lib.types.Summary; +import io.ably.pubsub.http.HttpCore; +import io.ably.pubsub.platform.Platform; +import io.ably.pubsub.types.AblyException; +import io.ably.pubsub.types.Annotation; +import io.ably.pubsub.types.AnnotationAction; +import io.ably.pubsub.types.ErrorInfo; +import io.ably.pubsub.types.Message; +import io.ably.pubsub.types.MessageAnnotations; +import io.ably.pubsub.types.MessageExtras; +import io.ably.pubsub.types.MessageVersion; +import io.ably.pubsub.types.PresenceMessage; +import io.ably.pubsub.types.ProtocolMessage; +import io.ably.pubsub.types.Summary; import org.msgpack.core.MessagePack; import org.msgpack.core.MessagePack.PackerConfig; import org.msgpack.core.MessagePack.UnpackerConfig; diff --git a/lib/src/main/java/io/ably/pubsub/util/Side.java b/lib/src/main/java/io/ably/pubsub/util/Side.java new file mode 100644 index 000000000..79a0c8d85 --- /dev/null +++ b/lib/src/main/java/io/ably/pubsub/util/Side.java @@ -0,0 +1,67 @@ +package io.ably.pubsub.util; + +import io.ably.pubsub.types.ClientOptions; + +import java.util.HashMap; +import java.util.Map; + +/** + * Internal helper shared by the {@code io.ably.pubsub:device} and {@code io.ably.pubsub:server} + * door artifacts. It is compiled into each artifact's output from a shared source directory + * rather than published, so that the two artifacts can share this code without a third + * artifact existing for it to live in. + *

+ * The package split keeps {@code io.ably.pubsub:core} itself as the shared core, so nothing here may + * grow into a general abstraction over the core: it exists only to stamp the side a package + * declares. + */ +public final class Side { + private Side() {} + + /* + * The `-device` / `-server` suffix on both identifiers below is load-bearing, not + * cosmetic. On API-key auth the realtime system grants the server exemption by matching + * an agent entry ending in `-server`, and an identifier that is not yet in the + * ably-common registry is classified by that suffix alone. Renaming either without + * preserving its suffix silently reclassifies every client the package constructs. + * + * Both live here rather than in the package that uses each, so the naming scheme can be + * changed in one place. + */ + + /** The agent identifier declaring the device side, sent by {@code io.ably.pubsub:device}. */ + public static final String DEVICE_AGENT_IDENTIFIER = "ably-pubsub-device"; + + /** + * The agent identifier declaring the server side, sent by {@code io.ably.pubsub:server}. + *

+ * This is the entry that earns the MAU exemption on API-key auth, so its {@code -server} + * suffix is the one with billing consequences. + */ + public static final String SERVER_AGENT_IDENTIFIER = "ably-pubsub-server"; + + /** + * Injects a side agent identifier into the provided {@code ClientOptions} instance. + * The method adds the specified agent identifier to the {@code agents} map in the given + * {@code ClientOptions} object. If the {@code agents} map does not exist, a new one is created. + * + * @param options the {@code ClientOptions} instance to which the agent identifier will be added. + * If {@code null}, the method returns {@code null}. + * @param identifier the agent identifier to be injected into the {@code ClientOptions} instance. + * This identifier is used for specifying and classifying the type of client. + * @return the updated {@code ClientOptions} instance with the injected agent identifier. + * Returns {@code null} if the input {@code options} is {@code null}. + */ + public static ClientOptions injectSideAgent(ClientOptions options, String identifier) { + if (options == null) { + return null; + } + Map agents = new HashMap<>(); + if (options.agents != null) { + agents.putAll(options.agents); + } + agents.put(identifier, null); + options.agents = agents; + return options; + } +} diff --git a/lib/src/main/java/io/ably/lib/util/StringUtils.java b/lib/src/main/java/io/ably/pubsub/util/StringUtils.java similarity index 91% rename from lib/src/main/java/io/ably/lib/util/StringUtils.java rename to lib/src/main/java/io/ably/pubsub/util/StringUtils.java index d527fa105..e0a33a26b 100644 --- a/lib/src/main/java/io/ably/lib/util/StringUtils.java +++ b/lib/src/main/java/io/ably/pubsub/util/StringUtils.java @@ -1,7 +1,7 @@ -package io.ably.lib.util; +package io.ably.pubsub.util; import com.google.gson.JsonElement; -import io.ably.lib.http.HttpCore; +import io.ably.pubsub.http.HttpCore; public class StringUtils { diff --git a/lib/src/main/java/io/ably/lib/util/SystemClock.java b/lib/src/main/java/io/ably/pubsub/util/SystemClock.java similarity index 91% rename from lib/src/main/java/io/ably/lib/util/SystemClock.java rename to lib/src/main/java/io/ably/pubsub/util/SystemClock.java index d3dcf540a..a34acd187 100644 --- a/lib/src/main/java/io/ably/lib/util/SystemClock.java +++ b/lib/src/main/java/io/ably/pubsub/util/SystemClock.java @@ -1,10 +1,10 @@ -package io.ably.lib.util; +package io.ably.pubsub.util; import java.util.Timer; import java.util.TimerTask; -import io.ably.lib.debug.DebugOptions; -import io.ably.lib.types.ClientOptions; +import io.ably.pubsub.debug.DebugOptions; +import io.ably.pubsub.types.ClientOptions; public class SystemClock implements Clock { public static final SystemClock INSTANCE = new SystemClock(); diff --git a/lib/src/main/java/io/ably/lib/util/TimerInstance.java b/lib/src/main/java/io/ably/pubsub/util/TimerInstance.java similarity index 72% rename from lib/src/main/java/io/ably/lib/util/TimerInstance.java rename to lib/src/main/java/io/ably/pubsub/util/TimerInstance.java index 0b9d0f6bb..f377d21e9 100644 --- a/lib/src/main/java/io/ably/lib/util/TimerInstance.java +++ b/lib/src/main/java/io/ably/pubsub/util/TimerInstance.java @@ -1,4 +1,4 @@ -package io.ably.lib.util; +package io.ably.pubsub.util; @FunctionalInterface public interface TimerInstance { diff --git a/lib/src/test/java/io/ably/lib/test/rest/RestChannelTest.java b/lib/src/test/java/io/ably/lib/test/rest/RestChannelTest.java deleted file mode 100644 index 5d7afc300..000000000 --- a/lib/src/test/java/io/ably/lib/test/rest/RestChannelTest.java +++ /dev/null @@ -1,48 +0,0 @@ -package io.ably.lib.test.rest; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotEquals; -import static org.junit.Assert.assertTrue; - -import io.ably.lib.rest.AblyRest; -import io.ably.lib.rest.Channel; -import io.ably.lib.test.common.Setup; -import io.ably.lib.types.AblyException; -import io.ably.lib.types.ClientOptions; -import org.junit.Test; - -/** - * Test for basic Channel operation not related to publish or history - */ -public class RestChannelTest { - /** - * Test if ably.channel.get() returns same object if the same name is given - * Tests RTN2, RTN3, RSN3a, RSN4a - */ - @Test - public void channel_object_caching() throws AblyException { - Setup.TestVars testVars = Setup.getTestVars(); - ClientOptions opts = new ClientOptions(testVars.keys[0].keyStr); - AblyRest ablyRest = new AblyRest(opts); - - Channel channel1 = ablyRest.channels.get("channel_1"); - Channel channel2 = ablyRest.channels.get("channel_2"); - - Channel channel1_copy = ablyRest.channels.get("channel_1"); - - assertEquals("Verify channel objects are cached", channel1, channel1_copy); - assertNotEquals("Verify channel objects are different if different names are requested", channel1, channel2); - - /* Test channel enumeration */ - assertEquals("Verify total number of channels", ablyRest.channels.size(), 2); - assertTrue("Verify there is channel 1 in the list", ablyRest.channels.containsKey("channel_1")); - assertTrue("Verify there is channel 2 in the list", ablyRest.channels.containsKey("channel_2")); - for (final Channel channel : ablyRest.channels.values()) { - assertTrue("Verify correct channels are in the hashmap", - channel == channel1 || channel == channel2); - } - ablyRest.channels.release("channel_1"); - channel1_copy = ablyRest.channels.get("channel_1"); - assertNotEquals("Verify channel is re-created after release", channel1, channel1_copy); - } -} diff --git a/lib/src/test/java/io/ably/lib/test/util/StatsWriter.java b/lib/src/test/java/io/ably/lib/test/util/StatsWriter.java deleted file mode 100644 index 1040d6c87..000000000 --- a/lib/src/test/java/io/ably/lib/test/util/StatsWriter.java +++ /dev/null @@ -1,13 +0,0 @@ -package io.ably.lib.test.util; - -import io.ably.lib.http.HttpCore; -import io.ably.lib.http.HttpUtils; -import io.ably.lib.types.AblyException; -import io.ably.lib.types.Stats; -import io.ably.lib.util.Serialisation; - -public class StatsWriter { - public static HttpCore.RequestBody asJsonRequest(Stats[] stats) throws AblyException { - return new HttpUtils.JsonRequestBody(Serialisation.gson.toJson(stats)); - } -} diff --git a/lib/src/test/java/io/ably/lib/transport/DefaultsTest.java b/lib/src/test/java/io/ably/lib/transport/DefaultsTest.java deleted file mode 100644 index ae41df572..000000000 --- a/lib/src/test/java/io/ably/lib/transport/DefaultsTest.java +++ /dev/null @@ -1,25 +0,0 @@ -package io.ably.lib.transport; - -import org.junit.Test; - -import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; - -public class DefaultsTest { - - @Test - public void protocol_version_CSV2() { - assertThat(Defaults.ABLY_PROTOCOL_VERSION, is("6")); - } - - @Test - public void environmentFallbackHosts() { - assertThat(Defaults.getEnvironmentFallbackHosts("sandbox"), is(new String[] { - "sandbox-a-fallback.ably-realtime.com", - "sandbox-b-fallback.ably-realtime.com", - "sandbox-c-fallback.ably-realtime.com", - "sandbox-d-fallback.ably-realtime.com", - "sandbox-e-fallback.ably-realtime.com" - })); - } -} diff --git a/lib/src/test/java/io/ably/lib/transport/HostsTest.java b/lib/src/test/java/io/ably/lib/transport/HostsTest.java deleted file mode 100644 index ac5e1cf26..000000000 --- a/lib/src/test/java/io/ably/lib/transport/HostsTest.java +++ /dev/null @@ -1,281 +0,0 @@ -package io.ably.lib.transport; - -import static org.hamcrest.Matchers.contains; -import static org.hamcrest.Matchers.containsInAnyOrder; -import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.not; -import static org.hamcrest.Matchers.nullValue; -import static org.junit.Assert.assertThat; -import static org.junit.Assert.fail; - -import io.ably.lib.types.AblyException; -import io.ably.lib.types.ClientOptions; -import java.util.ArrayList; -import java.util.List; -import org.junit.Test; - -public class HostsTest { - - private final ClientOptions options = new ClientOptions(); - - /** - * Tests for Hosts class (fallback hosts). - */ - @Test - public void hosts_fallback() throws AblyException { - // When - Hosts hosts = new Hosts(Defaults.HOST_REALTIME, Defaults.HOST_REALTIME, options); - - // Then - List fallbackHosts = collectFallbackHosts(hosts); - assertThat(hosts.getPrimaryHost(), is(Defaults.HOST_REALTIME)); - // the returned fallback hosts should have the same elements as default host fallbacks - assertThat(fallbackHosts, containsInAnyOrder(Defaults.HOST_FALLBACKS)); - // expect the fallback hosts to be shuffled - assertThat(fallbackHosts, not(contains(Defaults.HOST_FALLBACKS))); - } - - /** - * Expect an exception when setting both realtimeHost and environment. - */ - @Test(expected = AblyException.class) - public void hosts_host_and_environment() throws AblyException { - // Given - options.environment = "myenv"; - - // When - new Hosts("overridden.ably.io", Defaults.HOST_REALTIME, options); - } - - /** - * Configuration errors carry Ably code 40000 and HTTP status code 400. - */ - @Test - public void hosts_invalid_options_error_codes() { - options.environment = "myenv"; - try { - new Hosts("overridden.ably.io", Defaults.HOST_REALTIME, options); - fail("expected AblyException"); - } catch (AblyException e) { - assertThat(e.errorInfo.code, is(40000)); - assertThat(e.errorInfo.statusCode, is(400)); - } - } - - /** - * Expect a null, when we provide empty array of fallback hosts - */ - @Test - public void hosts_fallback_empty_array() throws AblyException { - // Given - options.fallbackHosts = new String[] {}; - - // When - Hosts hosts = new Hosts(Defaults.HOST_REALTIME, Defaults.HOST_REALTIME, options); - - // Then - assertThat(hosts.getFallback(Defaults.HOST_REALTIME), nullValue()); - } - - /** - * Expect that returned host is contained within custom host list in options, - * but in shuffled order and the right number of them. - */ - @Test - public void hosts_fallback_custom_hosts() throws AblyException { - // Given - String[] customHosts = { "F.ably-realtime.com", "G.ably-realtime.com", "H.ably-realtime.com", "I.ably-realtime.com", "J.ably-realtime.com", "K.ably-realtime.com" }; - options.fallbackHosts = customHosts; - - // When - Hosts hosts = new Hosts(Defaults.HOST_REALTIME, Defaults.HOST_REALTIME, options); - - // Then - List fallbackHosts = collectFallbackHosts(hosts); - assertThat(hosts.getPrimaryHost(), is(Defaults.HOST_REALTIME)); - // the returned fallback hosts should have the same elements as custom host fallbacks - assertThat(fallbackHosts, containsInAnyOrder(customHosts)); - // expect the fallback hosts to be shuffled - assertThat(fallbackHosts, not(contains(customHosts))); - } - - /** - * Expect that returned host is contained within default host list - */ - @Test - public void hosts_fallback_no_custom_hosts() throws AblyException { - // When - Hosts hosts = new Hosts(null, Defaults.HOST_REALTIME, options); - - // Then - List fallbackHosts = collectFallbackHosts(hosts); - assertThat(hosts.getPrimaryHost(), is(Defaults.HOST_REALTIME)); - // the returned fallback hosts should have the same elements as default host fallbacks - assertThat(fallbackHosts, containsInAnyOrder(Defaults.HOST_FALLBACKS)); - // expect the fallback hosts to be shuffled - assertThat(fallbackHosts, not(contains(Defaults.HOST_FALLBACKS))); - } - - /** - * Expect a null, when realtimeHost is non-default - */ - @Test - public void hosts_fallback_overridden_host() throws AblyException { - // Given - String host = "overridden.ably.io"; - - // When - Hosts hosts = new Hosts(host, Defaults.HOST_REALTIME, options); - - // Then - assertThat(hosts.getFallback(host), nullValue()); - } - - /** - * Expect that returned host is contained within default host list - * when realtimeHost is non-default and fallbackHostsUseDefault is set - */ - @Test - public void hosts_fallback_use_default() throws AblyException { - // Given - options.fallbackHostsUseDefault = true; - String host = "overridden.ably.io"; - - // When - Hosts hosts = new Hosts(host, Defaults.HOST_REALTIME, options); - - // Then - assertThat(hosts.getPrimaryHost(), is(host)); - // the returned fallback hosts should have the same elements as default host fallbacks - assertThat(collectFallbackHosts(hosts), containsInAnyOrder(Defaults.HOST_FALLBACKS)); - } - - /** - * It is not allowed to use default fallback hosts and at the same time - * provide custom fallback hosts. - */ - @Test(expected = AblyException.class) - public void hosts_fallback_use_default_and_set_fallback_hosts() throws AblyException { - // Given - options.fallbackHostsUseDefault = true; - options.fallbackHosts = new String[] { "custom.ably-realtime.com" }; - - // When - new Hosts(null, Defaults.HOST_REALTIME, options); - } - - /** - * Expect that returned fallback hosts containing the environment information. - */ - @Test - public void hosts_fallback_use_environment() throws AblyException { - // Given - options.environment = "sandbox"; - String[] expectedEnvironmentFallbackHosts = Defaults.getEnvironmentFallbackHosts(options.environment); - - // When - Hosts hosts = new Hosts(null, Defaults.HOST_REALTIME, options); - - // Then - assertThat(hosts.getPrimaryHost(), is("sandbox-" + Defaults.HOST_REALTIME)); - assertThat(collectFallbackHosts(hosts), containsInAnyOrder(expectedEnvironmentFallbackHosts)); - } - - /** - * Expect that returned default fallback hosts without environment according to RSC15g4. - */ - @Test - public void hosts_fallback_use_default_fallback_hosts_and_environment() throws AblyException { - // Given - options.fallbackHostsUseDefault = true; - options.environment = "sandbox"; - - // When - Hosts hosts = new Hosts(null, Defaults.HOST_REALTIME, options); - - // Then - assertThat(hosts.getPrimaryHost(), is("sandbox-" + Defaults.HOST_REALTIME)); - assertThat(collectFallbackHosts(hosts), containsInAnyOrder(Defaults.HOST_FALLBACKS)); - } - - /** - * Expect no fallback hosts if the custom port is specified. - */ - @Test - public void hosts_no_fallback_when_port_is_defined() throws AblyException { - // Given - options.port = 8080; - - // When - Hosts hosts = new Hosts(null, Defaults.HOST_REALTIME, options); - - // Then - assertThat(hosts.getFallback(Defaults.HOST_REALTIME), nullValue()); - } - - /** - * Expect no fallback hosts if the custom TLS port is specified. - */ - @Test - public void hosts_no_fallback_when_tlsport_is_defined() throws AblyException { - // Given - options.tlsPort = 8081; - - // When - Hosts hosts = new Hosts(null, Defaults.HOST_REALTIME, options); - - // Then - assertThat(hosts.getFallback(Defaults.HOST_REALTIME), nullValue()); - } - - /** - * It should return fallback hosts when custom fallbacks and port are provided. - */ - @Test - public void hosts_fallback_when_fallback_hosts_and_port_are_defined() throws AblyException { - // Given - options.port = 8081; - options.fallbackHosts = new String[] { "custom-fallback.ably.com" }; - - // When - Hosts hosts = new Hosts(null, Defaults.HOST_REALTIME, options); - - // Then - assertThat(hosts.getFallback(Defaults.HOST_REALTIME), is("custom-fallback.ably.com")); - } - - /** - * It should return fallback hosts when host, custom fallbacks, and port are provided. - */ - @Test - public void hosts_fallback_when_host_and_fallback_hosts_and_port_are_defined() throws AblyException { - // Given - options.tlsPort = 8081; - options.fallbackHosts = new String[] { "custom-fallback.ably.com" }; - - // When - Hosts hosts = new Hosts("custom.ably.com", Defaults.HOST_REALTIME, options); - - // Then - assertThat(hosts.getFallback("custom.ably.com"), is("custom-fallback.ably.com")); - } - - @Test(expected = AblyException.class) - public void hosts_use_default_fallback_hosts_and_tlsport_are_defined() throws AblyException { - // Given - options.tlsPort = 8081; - options.fallbackHostsUseDefault = true; - - // When - new Hosts(null, Defaults.HOST_REALTIME, options); - } - - private List collectFallbackHosts(Hosts hosts) { - List fallbackHosts = new ArrayList<>(); - String host = hosts.getPrimaryHost(); - while ((host = hosts.getFallback(host)) != null){ - fallbackHosts.add(host); - } - return fallbackHosts; - } -} diff --git a/lib/src/test/java/io/ably/lib/types/ClientOptionsTest.java b/lib/src/test/java/io/ably/lib/types/ClientOptionsTest.java deleted file mode 100644 index 3d482d95d..000000000 --- a/lib/src/test/java/io/ably/lib/types/ClientOptionsTest.java +++ /dev/null @@ -1,16 +0,0 @@ -package io.ably.lib.types; - -import static org.junit.Assert.assertTrue; - -import org.junit.Test; - -public class ClientOptionsTest { - - private final ClientOptions clientOptions = new ClientOptions(); - - @Test - public void should_support_idempotent_rest_publishing() { - // Then - assertTrue(clientOptions.idempotentRestPublishing); - } -} diff --git a/lib/src/test/java/io/ably/lib/chat/ChatMessagesTest.java b/lib/src/test/java/io/ably/pubsub/chat/ChatMessagesTest.java similarity index 94% rename from lib/src/test/java/io/ably/lib/chat/ChatMessagesTest.java rename to lib/src/test/java/io/ably/pubsub/chat/ChatMessagesTest.java index 0c9636439..37c04af26 100644 --- a/lib/src/test/java/io/ably/lib/chat/ChatMessagesTest.java +++ b/lib/src/test/java/io/ably/pubsub/chat/ChatMessagesTest.java @@ -1,15 +1,16 @@ -package io.ably.lib.chat; +package io.ably.pubsub.chat; import com.google.gson.JsonObject; -import io.ably.lib.realtime.AblyRealtime; -import io.ably.lib.realtime.Channel; -import io.ably.lib.realtime.ChannelState; -import io.ably.lib.test.common.Helpers; -import io.ably.lib.test.common.ParameterizedTest; -import io.ably.lib.types.ClientOptions; -import io.ably.lib.types.Message; -import io.ably.lib.types.MessageAction; -import io.ably.lib.types.MessageVersion; +import io.ably.pubsub.realtime.PubSubRealtimeClient; +import io.ably.pubsub.realtime.RealtimeClientFactory; +import io.ably.pubsub.realtime.Channel; +import io.ably.pubsub.realtime.ChannelState; +import io.ably.pubsub.test.common.Helpers; +import io.ably.pubsub.test.common.ParameterizedTest; +import io.ably.pubsub.types.ClientOptions; +import io.ably.pubsub.types.Message; +import io.ably.pubsub.types.MessageAction; +import io.ably.pubsub.types.MessageVersion; import org.junit.Assert; import org.junit.Test; @@ -27,11 +28,11 @@ public class ChatMessagesTest extends ParameterizedTest { public void test_room_message_is_published() { String roomId = "1234"; String channelName = roomId + "::$chat::$chatMessages"; - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; try { ClientOptions opts = createOptions(testVars.keys[7].keyStr); opts.clientId = "sandbox-client"; - ably = new AblyRealtime(opts); + ably = RealtimeClientFactory.create(opts); ChatRoom room = new ChatRoom(roomId, ably); /* create a channel and attach */ @@ -118,16 +119,16 @@ public void test_room_message_is_published() { public void test_room_message_is_updated() { String roomId = "1234"; String channelName = roomId + "::$chat::$chatMessages"; - AblyRealtime ablyClient1 = null; - AblyRealtime ablyClient2 = null; + PubSubRealtimeClient ablyClient1 = null; + PubSubRealtimeClient ablyClient2 = null; try { ClientOptions opts1 = createOptions(testVars.keys[7].keyStr); opts1.clientId = "clientId1"; - ablyClient1 = new AblyRealtime(opts1); + ablyClient1 = RealtimeClientFactory.create(opts1); ClientOptions opts2 = createOptions(testVars.keys[7].keyStr); opts2.clientId = "clientId2"; - ablyClient2 = new AblyRealtime(opts2); + ablyClient2 = RealtimeClientFactory.create(opts2); ChatRoom room = new ChatRoom(roomId, ablyClient1); @@ -231,16 +232,16 @@ public void test_room_message_is_updated() { public void test_room_message_is_deleted() { String roomId = "1234"; String channelName = roomId + "::$chat::$chatMessages"; - AblyRealtime ablyClient1 = null; - AblyRealtime ablyClient2 = null; + PubSubRealtimeClient ablyClient1 = null; + PubSubRealtimeClient ablyClient2 = null; try { ClientOptions opts1 = createOptions(testVars.keys[7].keyStr); opts1.clientId = "clientId1"; - ablyClient1 = new AblyRealtime(opts1); + ablyClient1 = RealtimeClientFactory.create(opts1); ClientOptions opts2 = createOptions(testVars.keys[7].keyStr); opts2.clientId = "clientId2"; - ablyClient2 = new AblyRealtime(opts2); + ablyClient2 = RealtimeClientFactory.create(opts2); ChatRoom room = new ChatRoom(roomId, ablyClient1); @@ -324,16 +325,16 @@ public void test_room_message_is_deleted() { public void test_room_message_create_update_delete() { String roomId = "1234"; String channelName = roomId + "::$chat::$chatMessages"; - AblyRealtime ablyClient1 = null; - AblyRealtime ablyClient2 = null; + PubSubRealtimeClient ablyClient1 = null; + PubSubRealtimeClient ablyClient2 = null; try { ClientOptions opts1 = createOptions(testVars.keys[7].keyStr); opts1.clientId = "clientId1"; - ablyClient1 = new AblyRealtime(opts1); + ablyClient1 = RealtimeClientFactory.create(opts1); ClientOptions opts2 = createOptions(testVars.keys[7].keyStr); opts2.clientId = "clientId2"; - ablyClient2 = new AblyRealtime(opts2); + ablyClient2 = RealtimeClientFactory.create(opts2); ChatRoom room = new ChatRoom(roomId, ablyClient1); @@ -444,16 +445,16 @@ public void test_room_message_create_update_delete() { public void test_operations_allowed_on_deleted_message() { String roomId = "1234"; String channelName = roomId + "::$chat::$chatMessages"; - AblyRealtime ablyClient1 = null; - AblyRealtime ablyClient2 = null; + PubSubRealtimeClient ablyClient1 = null; + PubSubRealtimeClient ablyClient2 = null; try { ClientOptions opts1 = createOptions(testVars.keys[7].keyStr); opts1.clientId = "clientId1"; - ablyClient1 = new AblyRealtime(opts1); + ablyClient1 = RealtimeClientFactory.create(opts1); ClientOptions opts2 = createOptions(testVars.keys[7].keyStr); opts2.clientId = "clientId2"; - ablyClient2 = new AblyRealtime(opts2); + ablyClient2 = RealtimeClientFactory.create(opts2); ChatRoom room = new ChatRoom(roomId, ablyClient1); diff --git a/lib/src/test/java/io/ably/lib/chat/ChatRoom.java b/lib/src/test/java/io/ably/pubsub/chat/ChatRoom.java similarity index 74% rename from lib/src/test/java/io/ably/lib/chat/ChatRoom.java rename to lib/src/test/java/io/ably/pubsub/chat/ChatRoom.java index 5c784a9c9..89fdbcd12 100644 --- a/lib/src/test/java/io/ably/lib/chat/ChatRoom.java +++ b/lib/src/test/java/io/ably/pubsub/chat/ChatRoom.java @@ -1,28 +1,28 @@ -package io.ably.lib.chat; +package io.ably.pubsub.chat; import com.google.gson.Gson; import com.google.gson.JsonElement; import com.google.gson.JsonObject; -import io.ably.lib.http.HttpCore; -import io.ably.lib.http.HttpUtils; -import io.ably.lib.rest.AblyRest; -import io.ably.lib.types.AblyException; -import io.ably.lib.types.ErrorInfo; -import io.ably.lib.types.HttpPaginatedResponse; -import io.ably.lib.types.Param; +import io.ably.pubsub.http.HttpCore; +import io.ably.pubsub.http.HttpUtils; +import io.ably.pubsub.http.PubSubHttpClient; +import io.ably.pubsub.types.AblyException; +import io.ably.pubsub.types.ErrorInfo; +import io.ably.pubsub.types.HttpPaginatedResponse; +import io.ably.pubsub.types.Param; import java.util.Arrays; import java.util.Map; import java.util.Optional; public class ChatRoom { - private final AblyRest ablyRest; + private final PubSubHttpClient pubSubHttpClient; private final String roomId; private final Gson gson = new Gson(); - protected ChatRoom(String roomId, AblyRest ablyRest) { + protected ChatRoom(String roomId, PubSubHttpClient pubSubHttpClient) { this.roomId = roomId; - this.ablyRest = ablyRest; + this.pubSubHttpClient = pubSubHttpClient; } public JsonElement sendMessage(SendMessageParams params) throws Exception { @@ -58,8 +58,8 @@ public static class DeleteMessageParams { } protected Optional makeAuthorizedRequest(String url, String method, JsonElement body) throws AblyException { - HttpCore.RequestBody httpRequestBody = HttpUtils.requestBodyFromGson(body, ablyRest.options.useBinaryProtocol); - HttpPaginatedResponse response = ablyRest.request(method, url, new Param[] { new Param("v", 3) }, httpRequestBody, null); + HttpCore.RequestBody httpRequestBody = HttpUtils.requestBodyFromGson(body, pubSubHttpClient.options.useBinaryProtocol); + HttpPaginatedResponse response = pubSubHttpClient.request(method, url, new Param[] { new Param("v", 3) }, httpRequestBody, null); return Arrays.stream(response.items()).findFirst(); } } diff --git a/lib/src/test/java/io/ably/lib/rest/DeviceDetailsTest.java b/lib/src/test/java/io/ably/pubsub/http/DeviceDetailsTest.java similarity index 95% rename from lib/src/test/java/io/ably/lib/rest/DeviceDetailsTest.java rename to lib/src/test/java/io/ably/pubsub/http/DeviceDetailsTest.java index da0f386b7..d25d12bd5 100644 --- a/lib/src/test/java/io/ably/lib/rest/DeviceDetailsTest.java +++ b/lib/src/test/java/io/ably/pubsub/http/DeviceDetailsTest.java @@ -1,6 +1,6 @@ -package io.ably.lib.rest; +package io.ably.pubsub.http; -import io.ably.lib.util.JsonUtils; +import io.ably.pubsub.util.JsonUtils; import org.junit.Test; import static org.junit.Assert.assertTrue; diff --git a/lib/src/test/java/io/ably/lib/http/HttpAuthTypeTest.java b/lib/src/test/java/io/ably/pubsub/http/HttpAuthTypeTest.java similarity index 97% rename from lib/src/test/java/io/ably/lib/http/HttpAuthTypeTest.java rename to lib/src/test/java/io/ably/pubsub/http/HttpAuthTypeTest.java index 668406a7e..d987b88ca 100644 --- a/lib/src/test/java/io/ably/lib/http/HttpAuthTypeTest.java +++ b/lib/src/test/java/io/ably/pubsub/http/HttpAuthTypeTest.java @@ -1,4 +1,4 @@ -package io.ably.lib.http; +package io.ably.pubsub.http; import static org.junit.Assert.assertEquals; diff --git a/lib/src/test/java/io/ably/lib/http/HttpHelpersTest.java b/lib/src/test/java/io/ably/pubsub/http/HttpHelpersTest.java similarity index 96% rename from lib/src/test/java/io/ably/lib/http/HttpHelpersTest.java rename to lib/src/test/java/io/ably/pubsub/http/HttpHelpersTest.java index 039eb342a..9228e8a56 100644 --- a/lib/src/test/java/io/ably/lib/http/HttpHelpersTest.java +++ b/lib/src/test/java/io/ably/pubsub/http/HttpHelpersTest.java @@ -1,6 +1,6 @@ -package io.ably.lib.http; +package io.ably.pubsub.http; -import io.ably.lib.types.AblyException; +import io.ably.pubsub.types.AblyException; import org.junit.Test; import java.net.URL; diff --git a/lib/src/test/java/io/ably/pubsub/http/HttpUtilsTest.java b/lib/src/test/java/io/ably/pubsub/http/HttpUtilsTest.java new file mode 100644 index 000000000..631f20443 --- /dev/null +++ b/lib/src/test/java/io/ably/pubsub/http/HttpUtilsTest.java @@ -0,0 +1,32 @@ +package io.ably.pubsub.http; + +import org.junit.Test; + +import java.net.URL; + +import static org.junit.Assert.assertEquals; + +public class HttpUtilsTest { + + @Test + public void hostForUrl_ipv6Literal_isBracketed() { + assertEquals("[::1]", HttpUtils.hostForUrl("::1")); + assertEquals("[2001:db8::1]", HttpUtils.hostForUrl("2001:db8::1")); + } + + @Test + public void hostForUrl_otherHosts_areUnchanged() { + assertEquals("[::1]", HttpUtils.hostForUrl("[::1]")); + assertEquals("127.0.0.1", HttpUtils.hostForUrl("127.0.0.1")); + assertEquals("localhost", HttpUtils.hostForUrl("localhost")); + assertEquals("main.realtime.ably.net", HttpUtils.hostForUrl("main.realtime.ably.net")); + } + + @Test + public void buildURL_ipv6Host_addressesHostAndPort() { + URL url = HttpUtils.buildURL("http://", "::1", 8080, "/time", null); + assertEquals("http://[::1]:8080/time", url.toString()); + assertEquals("[::1]", url.getHost()); + assertEquals(8080, url.getPort()); + } +} diff --git a/lib/src/test/java/io/ably/lib/test/common/Helpers.java b/lib/src/test/java/io/ably/pubsub/test/common/Helpers.java similarity index 95% rename from lib/src/test/java/io/ably/lib/test/common/Helpers.java rename to lib/src/test/java/io/ably/pubsub/test/common/Helpers.java index 35d2622fc..1153e7bde 100644 --- a/lib/src/test/java/io/ably/lib/test/common/Helpers.java +++ b/lib/src/test/java/io/ably/pubsub/test/common/Helpers.java @@ -1,4 +1,4 @@ -package io.ably.lib.test.common; +package io.ably.pubsub.test.common; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; @@ -30,35 +30,36 @@ import com.google.gson.JsonElement; import com.google.gson.JsonObject; -import io.ably.lib.debug.DebugOptions.RawHttpListener; -import io.ably.lib.debug.DebugOptions.RawProtocolListener; -import io.ably.lib.http.HttpCore; -import io.ably.lib.http.HttpUtils; -import io.ably.lib.network.HttpRequest; -import io.ably.lib.realtime.AblyRealtime; -import io.ably.lib.realtime.Channel; -import io.ably.lib.realtime.Channel.MessageListener; -import io.ably.lib.realtime.ChannelEvent; -import io.ably.lib.realtime.ChannelState; -import io.ably.lib.realtime.ChannelStateListener; -import io.ably.lib.realtime.CompletionListener; -import io.ably.lib.realtime.Connection; -import io.ably.lib.realtime.ConnectionState; -import io.ably.lib.realtime.ConnectionStateListener; -import io.ably.lib.realtime.Presence.PresenceListener; -import io.ably.lib.transport.ConnectionManager; -import io.ably.lib.types.AblyException; -import io.ably.lib.types.BaseMessage; -import io.ably.lib.types.Callback; -import io.ably.lib.types.ErrorInfo; -import io.ably.lib.types.ErrorResponse; -import io.ably.lib.types.Message; -import io.ably.lib.types.PresenceMessage; -import io.ably.lib.types.ProtocolMessage; -import io.ably.lib.types.ProtocolMessage.Action; -import io.ably.lib.util.Base64Coder; -import io.ably.lib.util.Log; -import io.ably.lib.util.Serialisation; +import io.ably.pubsub.debug.DebugOptions.RawHttpListener; +import io.ably.pubsub.debug.DebugOptions.RawProtocolListener; +import io.ably.pubsub.http.HttpCore; +import io.ably.pubsub.http.HttpUtils; +import io.ably.pubsub.network.HttpRequest; +import io.ably.pubsub.realtime.PubSubRealtimeClient; +import io.ably.pubsub.realtime.Channel; +import io.ably.pubsub.realtime.Channel.MessageListener; +import io.ably.pubsub.realtime.ChannelEvent; +import io.ably.pubsub.realtime.ChannelState; +import io.ably.pubsub.realtime.ChannelStateListener; +import io.ably.pubsub.realtime.CompletionListener; +import io.ably.pubsub.realtime.Connection; +import io.ably.pubsub.realtime.ConnectionState; +import io.ably.pubsub.realtime.ConnectionStateListener; +import io.ably.pubsub.realtime.Presence.PresenceListener; +import io.ably.pubsub.transport.ConnectionManager; +import io.ably.pubsub.types.AblyException; +import io.ably.pubsub.types.BaseMessage; +import io.ably.pubsub.types.Callback; +import io.ably.pubsub.types.PublishResult; +import io.ably.pubsub.types.ErrorInfo; +import io.ably.pubsub.types.ErrorResponse; +import io.ably.pubsub.types.Message; +import io.ably.pubsub.types.PresenceMessage; +import io.ably.pubsub.types.ProtocolMessage; +import io.ably.pubsub.types.ProtocolMessage.Action; +import io.ably.pubsub.util.Base64Coder; +import io.ably.pubsub.util.Log; +import io.ably.pubsub.util.Serialisation; import org.hamcrest.Matcher; import static junit.framework.Assert.assertTrue; @@ -161,7 +162,7 @@ private static class Counter { * @author paddy * */ - public static class CompletionWaiter implements CompletionListener { + public static class CompletionWaiter implements CompletionListener, Callback { public boolean success; public int successCount; public ErrorInfo error; @@ -230,6 +231,15 @@ public void onError(ErrorInfo reason) { notifyAll(); } } + + /** + * Callback<PublishResult> method, so that the same waiter can be passed to the + * publish overloads that report a PublishResult. + */ + @Override + public void onSuccess(PublishResult result) { + onSuccess(); + } } /** @@ -414,8 +424,8 @@ public PresenceMessage contains(String clientId, String connectionId, PresenceMe public static class MutableConnectionManager { ConnectionManager connectionManager; - public MutableConnectionManager(AblyRealtime ablyRealtime) { - this.connectionManager = ablyRealtime.connection.connectionManager; + public MutableConnectionManager(PubSubRealtimeClient realtimeClient) { + this.connectionManager = realtimeClient.connection.connectionManager; } public void setField(String fieldName, long value) { @@ -869,7 +879,7 @@ public static class CompletionSet { * @author paddy * */ - public class Member implements CompletionListener { + public class Member implements CompletionListener, Callback { @Override public void onSuccess() { synchronized(CompletionSet.this) { @@ -878,6 +888,10 @@ public void onSuccess() { } } @Override + public void onSuccess(PublishResult result) { + onSuccess(); + } + @Override public void onError(ErrorInfo reason) { synchronized(CompletionSet.this) { pending.remove(this); diff --git a/lib/src/test/java/io/ably/lib/test/common/ParameterizedTest.java b/lib/src/test/java/io/ably/pubsub/test/common/ParameterizedTest.java similarity index 93% rename from lib/src/test/java/io/ably/lib/test/common/ParameterizedTest.java rename to lib/src/test/java/io/ably/pubsub/test/common/ParameterizedTest.java index 8893bb245..b46dc3496 100644 --- a/lib/src/test/java/io/ably/lib/test/common/ParameterizedTest.java +++ b/lib/src/test/java/io/ably/pubsub/test/common/ParameterizedTest.java @@ -1,4 +1,4 @@ -package io.ably.lib.test.common; +package io.ably.pubsub.test.common; import java.text.SimpleDateFormat; import java.util.Arrays; @@ -6,7 +6,7 @@ import java.util.HashMap; import java.util.Map; -import io.ably.lib.types.Param; +import io.ably.pubsub.types.Param; import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Rule; @@ -16,9 +16,9 @@ import org.junit.runners.Parameterized.Parameter; import org.junit.runners.Parameterized.Parameters; -import io.ably.lib.debug.DebugOptions; -import io.ably.lib.types.AblyException; -import io.ably.lib.types.ClientOptions; +import io.ably.pubsub.debug.DebugOptions; +import io.ably.pubsub.types.AblyException; +import io.ably.pubsub.types.ClientOptions; @RunWith(Parameterized.class) public class ParameterizedTest { diff --git a/lib/src/test/java/io/ably/lib/test/common/Setup.java b/lib/src/test/java/io/ably/pubsub/test/common/Setup.java similarity index 80% rename from lib/src/test/java/io/ably/lib/test/common/Setup.java rename to lib/src/test/java/io/ably/pubsub/test/common/Setup.java index 889aba74f..9cc6a4347 100644 --- a/lib/src/test/java/io/ably/lib/test/common/Setup.java +++ b/lib/src/test/java/io/ably/pubsub/test/common/Setup.java @@ -1,25 +1,26 @@ -package io.ably.lib.test.common; +package io.ably.pubsub.test.common; import java.io.IOException; import java.util.Date; import com.google.gson.Gson; -import io.ably.lib.http.Http; -import io.ably.lib.http.HttpCore; -import io.ably.lib.http.HttpScheduler; -import io.ably.lib.http.HttpUtils; -import io.ably.lib.http.HttpHelpers; -import io.ably.lib.rest.AblyRest; -import io.ably.lib.test.loader.ArgumentLoader; -import io.ably.lib.test.loader.ResourceLoader; -import io.ably.lib.types.AblyException; -import io.ably.lib.types.Callback; -import io.ably.lib.types.ClientOptions; -import io.ably.lib.types.ErrorInfo; -import io.ably.lib.types.PresenceMessage; -import io.ably.lib.util.Serialisation; -import io.ably.lib.debug.DebugOptions; +import io.ably.pubsub.http.HttpRequester; +import io.ably.pubsub.http.HttpCore; +import io.ably.pubsub.http.HttpScheduler; +import io.ably.pubsub.http.HttpUtils; +import io.ably.pubsub.http.HttpHelpers; +import io.ably.pubsub.http.HttpClientFactory; +import io.ably.pubsub.http.PubSubHttpClient; +import io.ably.pubsub.test.loader.ArgumentLoader; +import io.ably.pubsub.test.loader.ResourceLoader; +import io.ably.pubsub.types.AblyException; +import io.ably.pubsub.types.Callback; +import io.ably.pubsub.types.ClientOptions; +import io.ably.pubsub.types.ErrorInfo; +import io.ably.pubsub.types.PresenceMessage; +import io.ably.pubsub.util.Serialisation; +import io.ably.pubsub.debug.DebugOptions; public class Setup { /** @@ -119,9 +120,7 @@ public static TestParameters getDefault() { } public static class TestVars extends AppSpec { - public String restHost; - public String realtimeHost; - public String environment; + public String endpoint; public int port; public int tlsPort; public boolean tls; @@ -155,9 +154,7 @@ public void fillInOptions(ClientOptions opts) { public void fillInOptions(ClientOptions opts, TestParameters params) { if(params == null) { params = TestParameters.getDefault(); } opts.useBinaryProtocol = params.useBinaryProtocol; - opts.restHost = restHost; - opts.realtimeHost = realtimeHost; - opts.environment = environment; + opts.endpoint = endpoint; opts.port = port; opts.tlsPort = tlsPort; opts.tls = tls; @@ -170,22 +167,15 @@ public static synchronized TestVars getTestVars() { private static TestVars __getTestVars() { if(testVars == null) { - host = argumentLoader.getTestArgument("ABLY_REST_HOST"); - environment = argumentLoader.getTestArgument("ABLY_ENV"); - if(environment == null) { - environment = "sandbox"; - } - - if(host != null) { - wsHost = argumentLoader.getTestArgument("ABLY_REALTIME_HOST"); - if(wsHost == null) - wsHost = host; + endpoint = argumentLoader.getTestArgument("ABLY_ENDPOINT"); + if(endpoint == null) { + endpoint = "nonprod:sandbox"; } if(argumentLoader.getTestArgument("ABLY_PORT") != null) { port = Integer.valueOf(argumentLoader.getTestArgument("ABLY_PORT")); tlsPort = Integer.valueOf(argumentLoader.getTestArgument("ABLY_TLS_PORT")); - } else if((host != null && host.contains("local")) || environment.equals("local")) { + } else if(endpoint.contains("local")) { port = 8080; tlsPort = 8081; } else { @@ -201,12 +191,11 @@ private static TestVars __getTestVars() { * but we are only instancing the library to use the http * convenience methods */ opts.key = "none:none"; - opts.restHost = host; - opts.environment = environment; + opts.endpoint = endpoint; opts.port = port; opts.tlsPort = tlsPort; opts.tls = true; - ably = new AblyRest(opts); + ably = HttpClientFactory.create(opts); } catch(AblyException e) { TerminationReason.UNABLE_TO_INSTANCE_REST.exit(e); } @@ -228,9 +217,7 @@ public TestVars handleResponse(HttpCore.Response response, ErrorInfo error) thro } TestVars result = (TestVars)Serialisation.gson.fromJson(new String(response.body), TestVars.class); - result.restHost = host; - result.realtimeHost = wsHost; - result.environment = environment; + result.endpoint = endpoint; result.port = port; result.tlsPort = tlsPort; result.tls = true; @@ -252,13 +239,12 @@ private static void __clearTestVars() { if(testVars != null) { try { ClientOptions opts = new ClientOptions(testVars.keys[0].keyStr); - opts.restHost = host; - opts.environment = environment; + opts.endpoint = endpoint; opts.port = port; opts.tlsPort = tlsPort; opts.tls = true; - ably = new AblyRest(opts); - ably.http.request(new Http.Execute() { + ably = HttpClientFactory.create(opts); + ably.http.request(new HttpRequester.Execute() { @Override public void execute(HttpScheduler http, Callback callback) throws AblyException { http.del("/apps/" + testVars.appId, HttpUtils.defaultAcceptHeaders(false), null, null, true, callback); @@ -280,10 +266,8 @@ public void execute(HttpScheduler http, Callback callback) throws AblyExce private static ResourceLoader resourceLoader; private static final String specFile = "local/testAppSpec.json"; - private static AblyRest ably; - private static String environment; - private static String host; - private static String wsHost; + private static PubSubHttpClient ably; + private static String endpoint; private static int port; private static int tlsPort; diff --git a/lib/src/test/java/io/ably/lib/test/rest/RestAppStatsTest.java b/lib/src/test/java/io/ably/pubsub/test/http/HttpAppStatsTest.java similarity index 96% rename from lib/src/test/java/io/ably/lib/test/rest/RestAppStatsTest.java rename to lib/src/test/java/io/ably/pubsub/test/http/HttpAppStatsTest.java index dcee1a53b..840a9b341 100644 --- a/lib/src/test/java/io/ably/lib/test/rest/RestAppStatsTest.java +++ b/lib/src/test/java/io/ably/pubsub/test/http/HttpAppStatsTest.java @@ -1,17 +1,18 @@ -package io.ably.lib.test.rest; +package io.ably.pubsub.test.http; -import io.ably.lib.http.HttpHelpers; -import io.ably.lib.http.HttpUtils; -import io.ably.lib.rest.AblyRest; -import io.ably.lib.test.common.ParameterizedTest; -import io.ably.lib.test.common.Setup; -import io.ably.lib.test.util.StatsWriter; -import io.ably.lib.types.AblyException; -import io.ably.lib.types.ClientOptions; -import io.ably.lib.types.PaginatedResult; -import io.ably.lib.types.Param; -import io.ably.lib.types.Stats; -import io.ably.lib.types.StatsReader; +import io.ably.pubsub.http.HttpHelpers; +import io.ably.pubsub.http.HttpUtils; +import io.ably.pubsub.http.HttpClientFactory; +import io.ably.pubsub.http.PubSubHttpClient; +import io.ably.pubsub.test.common.ParameterizedTest; +import io.ably.pubsub.test.common.Setup; +import io.ably.pubsub.test.util.StatsWriter; +import io.ably.pubsub.types.AblyException; +import io.ably.pubsub.types.ClientOptions; +import io.ably.pubsub.types.PaginatedResult; +import io.ably.pubsub.types.Param; +import io.ably.pubsub.types.Stats; +import io.ably.pubsub.types.StatsReader; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; @@ -26,22 +27,22 @@ import static org.junit.Assert.fail; @SuppressWarnings("deprecation") -public class RestAppStatsTest extends ParameterizedTest { +public class HttpAppStatsTest extends ParameterizedTest { - private AblyRest ably; + private PubSubHttpClient ably; private static String[] intervalIds; @Before public void setUpBefore() throws Exception { ClientOptions opts = createOptions(testVars.keys[0].keyStr); - ably = new AblyRest(opts); + ably = HttpClientFactory.create(opts); } @BeforeClass public static void populateStats() { try { ClientOptions opts = testVars.createOptions(testVars.keys[0].keyStr, Setup.TestParameters.TEXT); - AblyRest ably = new AblyRest(opts); + PubSubHttpClient ably = HttpClientFactory.create(opts); /* get time, preferring time from Ably */ long currentTime = System.currentTimeMillis(); try { diff --git a/lib/src/test/java/io/ably/lib/test/rest/RestAuthAttributeTest.java b/lib/src/test/java/io/ably/pubsub/test/http/HttpAuthAttributeTest.java similarity index 86% rename from lib/src/test/java/io/ably/lib/test/rest/RestAuthAttributeTest.java rename to lib/src/test/java/io/ably/pubsub/test/http/HttpAuthAttributeTest.java index 8f4b98a78..0c35ace3b 100644 --- a/lib/src/test/java/io/ably/lib/test/rest/RestAuthAttributeTest.java +++ b/lib/src/test/java/io/ably/pubsub/test/http/HttpAuthAttributeTest.java @@ -1,11 +1,12 @@ -package io.ably.lib.test.rest; - -import io.ably.lib.rest.AblyRest; -import io.ably.lib.rest.Auth; -import io.ably.lib.test.common.ParameterizedTest; -import io.ably.lib.types.AblyException; -import io.ably.lib.types.Capability; -import io.ably.lib.types.ClientOptions; +package io.ably.pubsub.test.http; + +import io.ably.pubsub.http.HttpClientFactory; +import io.ably.pubsub.http.PubSubHttpClient; +import io.ably.pubsub.http.Auth; +import io.ably.pubsub.test.common.ParameterizedTest; +import io.ably.pubsub.types.AblyException; +import io.ably.pubsub.types.Capability; +import io.ably.pubsub.types.ClientOptions; import org.junit.Before; import org.junit.Ignore; import org.junit.Test; @@ -25,15 +26,15 @@ /** * Created by VOstopolets on 9/3/16. */ -public class RestAuthAttributeTest extends ParameterizedTest { +public class HttpAuthAttributeTest extends ParameterizedTest { - private AblyRest ably; + private PubSubHttpClient ably; @Before public void setupClient() throws Exception { ClientOptions opts = createOptions(testVars.keys[0].keyStr); opts.useTokenAuth = true; - ably = new AblyRest(opts); + ably = HttpClientFactory.create(opts); } /** @@ -60,7 +61,7 @@ public void auth_stores_options_params() { /* init custom AuthOptions */ Auth.AuthOptions authOptions = new Auth.AuthOptions() {{ authCallback = new Auth.TokenCallback() { - private AblyRest ably = new AblyRest(createOptions(testVars.keys[0].keyStr)); + private PubSubHttpClient ably = HttpClientFactory.create(createOptions(testVars.keys[0].keyStr)); @Override public Object getTokenRequest(Auth.TokenParams params) throws AblyException { @@ -70,11 +71,8 @@ public Object getTokenRequest(Auth.TokenParams params) throws AblyException { key = testVars.keys[1].keyStr; }}; - /* authorise with custom options - * Deliberate use of British spelling alias authorise() to check that - * it works (0.9 RSA10l) */ - @SuppressWarnings("deprecation") - Auth.TokenDetails tokenDetails1 = ably.auth.authorise(tokenParams, authOptions); + /* authorize with custom options */ + Auth.TokenDetails tokenDetails1 = ably.auth.authorize(tokenParams, authOptions); /* Verify that, * tokenDetails1 isn't null, @@ -118,12 +116,7 @@ public void auth_stores_options_exception_querytime() { final String expectedClientId = "testClientId"; ClientOptions opts = createOptions(testVars.keys[0].keyStr); opts.clientId = expectedClientId; - AblyRest ablyForTime = new AblyRest(opts) { - @Override - public long time() throws AblyException { - return fakeServerTime; - } - }; + PubSubHttpClient ablyForTime = new FakeTimeHttpClient(opts, fakeServerTime); final Auth.AuthOptions authOptions = new Auth.AuthOptions(); authOptions.key = ablyForTime.options.key; authOptions.queryTime = true; @@ -172,7 +165,7 @@ public void auth_stores_options_exception_timestamp() { /* init ably for token */ final ClientOptions optsForToken = createOptions(testVars.keys[0].keyStr); optsForToken.clientId = expectedClientId; - final AblyRest ablyForToken = new AblyRest(optsForToken); + final PubSubHttpClient ablyForToken = HttpClientFactory.create(optsForToken); /* create custom token callback for capturing timestamp values */ final List timestampCapturedList = new ArrayList<>(); @@ -267,4 +260,24 @@ public Object getTokenRequest(Auth.TokenParams params) throws AblyException { fail("auth_custom_options_authorize: Unexpected exception"); } } + + /** + * A client that reports a fixed server time, for the tests that check whether an + * {@link AuthOptions#queryTime} request used it. A named subclass rather than an anonymous + * one because the client's constructor is not public. + */ + private static class FakeTimeHttpClient extends PubSubHttpClient { + private final long fakeServerTime; + + FakeTimeHttpClient(ClientOptions options, long fakeServerTime) throws AblyException { + super(options); + this.fakeServerTime = fakeServerTime; + } + + @Override + public long time() throws AblyException { + return fakeServerTime; + } + } + } diff --git a/lib/src/test/java/io/ably/lib/test/rest/RestAuthTest.java b/lib/src/test/java/io/ably/pubsub/test/http/HttpAuthTest.java similarity index 91% rename from lib/src/test/java/io/ably/lib/test/rest/RestAuthTest.java rename to lib/src/test/java/io/ably/pubsub/test/http/HttpAuthTest.java index d3553e7a8..4b9052816 100644 --- a/lib/src/test/java/io/ably/lib/test/rest/RestAuthTest.java +++ b/lib/src/test/java/io/ably/pubsub/test/http/HttpAuthTest.java @@ -1,30 +1,31 @@ -package io.ably.lib.test.rest; +package io.ably.pubsub.test.http; import fi.iki.elonen.NanoHTTPD; import fi.iki.elonen.router.RouterNanoHTTPD; -import io.ably.lib.debug.DebugOptions; -import io.ably.lib.http.HttpConstants; -import io.ably.lib.http.HttpCore; -import io.ably.lib.network.HttpRequest; -import io.ably.lib.rest.AblyRest; -import io.ably.lib.rest.Auth; -import io.ably.lib.rest.Auth.AuthMethod; -import io.ably.lib.rest.Auth.TokenCallback; -import io.ably.lib.rest.Auth.TokenDetails; -import io.ably.lib.rest.Auth.TokenParams; -import io.ably.lib.rest.Auth.TokenRequest; -import io.ably.lib.rest.Channel; -import io.ably.lib.test.common.Helpers; -import io.ably.lib.test.common.Helpers.RawHttpTracker; -import io.ably.lib.test.common.ParameterizedTest; -import io.ably.lib.test.util.TokenServer; -import io.ably.lib.types.AblyException; -import io.ably.lib.types.ClientOptions; -import io.ably.lib.types.ErrorInfo; -import io.ably.lib.types.Message; -import io.ably.lib.types.MessageSerializer; -import io.ably.lib.types.PaginatedResult; -import io.ably.lib.types.Param; +import io.ably.pubsub.debug.DebugOptions; +import io.ably.pubsub.http.HttpConstants; +import io.ably.pubsub.http.HttpCore; +import io.ably.pubsub.network.HttpRequest; +import io.ably.pubsub.http.HttpClientFactory; +import io.ably.pubsub.http.PubSubHttpClient; +import io.ably.pubsub.http.Auth; +import io.ably.pubsub.http.Auth.AuthMethod; +import io.ably.pubsub.http.Auth.TokenCallback; +import io.ably.pubsub.http.Auth.TokenDetails; +import io.ably.pubsub.http.Auth.TokenParams; +import io.ably.pubsub.http.Auth.TokenRequest; +import io.ably.pubsub.http.Channel; +import io.ably.pubsub.test.common.Helpers; +import io.ably.pubsub.test.common.Helpers.RawHttpTracker; +import io.ably.pubsub.test.common.ParameterizedTest; +import io.ably.pubsub.test.util.TokenServer; +import io.ably.pubsub.types.AblyException; +import io.ably.pubsub.types.ClientOptions; +import io.ably.pubsub.types.ErrorInfo; +import io.ably.pubsub.types.Message; +import io.ably.pubsub.types.MessageSerializer; +import io.ably.pubsub.types.PaginatedResult; +import io.ably.pubsub.types.Param; import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Rule; @@ -48,7 +49,7 @@ import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; -public class RestAuthTest extends ParameterizedTest { +public class HttpAuthTest extends ParameterizedTest { @Rule public Timeout testTimeout = Timeout.seconds(40); @@ -63,7 +64,7 @@ public class RestAuthTest extends ParameterizedTest { public static void auth_start_tokenserver() { try { ClientOptions opts = testVars.createOptions(testVars.keys[0].keyStr); - AblyRest ably = new AblyRest(opts); + PubSubHttpClient ably = HttpClientFactory.create(opts); tokenServer = new TokenServer(ably, 8982); tokenServer.start(); @@ -103,7 +104,7 @@ public static void auth_stop_tokenserver() { @Test public void authinit0() { try { - AblyRest ably = new AblyRest(testVars.keys[0].keyStr); + PubSubHttpClient ably = HttpClientFactory.create(new ClientOptions(testVars.keys[0].keyStr)); assertEquals("Unexpected Auth method mismatch", ably.auth.getAuthMethod(), AuthMethod.basic); assertEquals("Unexpected clientId mismatch", ably.auth.clientId, "*"); } catch (AblyException e) { @@ -121,7 +122,7 @@ public void auth_basic_nontls() { try { ClientOptions opts = createOptions(testVars.keys[0].keyStr); opts.tls = false; - AblyRest ably = new AblyRest(opts); + PubSubHttpClient ably = HttpClientFactory.create(opts); ably.stats(null); fail("Unexpected success calling with Basic auth over httpCore"); } catch (AblyException e) { @@ -138,7 +139,7 @@ public void authinit0_useTokenAuth() { try { ClientOptions opts = createOptions(testVars.keys[0].keyStr); opts.useTokenAuth = true; - AblyRest ably = new AblyRest(opts); + PubSubHttpClient ably = HttpClientFactory.create(opts); assertEquals("Unexpected Auth method mismatch", ably.auth.getAuthMethod(), AuthMethod.token); /* Spec: RSA12a */ assertEquals("Unexpected clientId mismatch", ably.auth.clientId, null); @@ -156,7 +157,7 @@ public void authinit1() { try { ClientOptions opts = new ClientOptions(); opts.token = "this_is_not_really_a_token"; - AblyRest ably = new AblyRest(opts); + PubSubHttpClient ably = HttpClientFactory.create(opts); assertEquals("Unexpected Auth method mismatch", ably.auth.getAuthMethod(), AuthMethod.token); /* Spec: RSA12a */ assertEquals("Unexpected clientId mismatch", ably.auth.clientId, null); @@ -174,8 +175,7 @@ public void authinit1() { public void authinit2() { try { ClientOptions opts = createOptions(); - opts.restHost = testVars.restHost; - opts.environment = testVars.environment; + opts.endpoint = testVars.endpoint; opts.port = testVars.port; opts.tlsPort = testVars.tlsPort; opts.tls = testVars.tls; @@ -185,7 +185,7 @@ public String getTokenRequest(TokenParams params) throws AblyException { authinit2_cbCalled = true; return "this_is_not_really_a_token_request"; }}; - AblyRest ably = new AblyRest(opts); + PubSubHttpClient ably = HttpClientFactory.create(opts); /* make a call to trigger token request */ try { ably.stats(null); @@ -209,7 +209,7 @@ public void authinit_clientId_auth_basic() { try { ClientOptions opts = createOptions(testVars.keys[0].keyStr); opts.clientId = "testClientId"; - AblyRest ably = new AblyRest(opts); + PubSubHttpClient ably = HttpClientFactory.create(opts); assertEquals("Unexpected Auth method mismatch", ably.auth.getAuthMethod(), AuthMethod.basic); assertEquals("Unexpected clientId mismatch", ably.auth.clientId, "testClientId"); } catch (AblyException e) { @@ -230,7 +230,7 @@ public void auth_clientid_null_before_auth() { ClientOptions opts = createOptions(testVars.keys[0].keyStr); opts.useTokenAuth = true; opts.defaultTokenParams = new TokenParams() {{ this.clientId = defaultClientId; }}; - AblyRest ably = new AblyRest(opts); + PubSubHttpClient ably = HttpClientFactory.create(opts); assertEquals("Unexpected Auth method mismatch", ably.auth.getAuthMethod(), AuthMethod.token); assertEquals("Unexpected clientId mismatch", ably.auth.clientId, null); ably.auth.authorize(null, null); @@ -250,7 +250,7 @@ public void authinit_token_implies_token() { try { ClientOptions opts = createOptions(testVars.keys[0].keyStr); opts.token = testVars.keys[0].keyStr; - AblyRest ably = new AblyRest(opts); + PubSubHttpClient ably = HttpClientFactory.create(opts); assertEquals("Unexpected Auth method mismatch", ably.auth.getAuthMethod(), AuthMethod.token); assertEquals("Unexpected clientId mismatch", ably.auth.clientId, null); } catch (AblyException e) { @@ -268,7 +268,7 @@ public void authinit_tokendetails_implies_token() { try { ClientOptions opts = createOptions(testVars.keys[0].keyStr); opts.tokenDetails = new TokenDetails() {{ token = testVars.keys[0].keyStr; }}; - AblyRest ably = new AblyRest(opts); + PubSubHttpClient ably = HttpClientFactory.create(opts); assertEquals("Unexpected Auth method mismatch", ably.auth.getAuthMethod(), AuthMethod.token); assertEquals("Unexpected clientId mismatch", ably.auth.clientId, null); } catch (AblyException e) { @@ -290,7 +290,7 @@ public void authinit_authcallback_implies_token() { public Object getTokenRequest(TokenParams params) throws AblyException { return null; }}; - AblyRest ably = new AblyRest(opts); + PubSubHttpClient ably = HttpClientFactory.create(opts); assertEquals("Unexpected Auth method mismatch", ably.auth.getAuthMethod(), AuthMethod.token); assertEquals("Unexpected clientId mismatch", ably.auth.clientId, null); } catch (AblyException e) { @@ -308,7 +308,7 @@ public void authinit_authurl_implies_token() { try { ClientOptions opts = createOptions(testVars.keys[0].keyStr); opts.authUrl = "http://auth.url"; - AblyRest ably = new AblyRest(opts); + PubSubHttpClient ably = HttpClientFactory.create(opts); assertEquals("Unexpected Auth method mismatch", ably.auth.getAuthMethod(), AuthMethod.token); } catch (AblyException e) { e.printStackTrace(); @@ -323,13 +323,13 @@ public void authinit_authurl_implies_token() { public void authinit4() { try { ClientOptions optsForToken = createOptions(testVars.keys[0].keyStr); - AblyRest ablyForToken = new AblyRest(optsForToken); + PubSubHttpClient ablyForToken = HttpClientFactory.create(optsForToken); TokenDetails tokenDetails = ablyForToken.auth.requestToken(null, null); assertNotNull("Expected token value", tokenDetails.token); ClientOptions opts = new ClientOptions(); opts.token = tokenDetails.token; - opts.environment = testVars.environment; - AblyRest ably = new AblyRest(opts); + opts.endpoint = testVars.endpoint; + PubSubHttpClient ably = HttpClientFactory.create(opts); assertEquals("Unexpected Auth method mismatch", ably.auth.getAuthMethod(), AuthMethod.token); assertEquals("Unexpected clientId mismatch", ably.auth.clientId, null); } catch (AblyException e) { @@ -346,9 +346,9 @@ public void authinit4() { public void auth_authURL_tokenrequest() { try { ClientOptions opts = createOptions(); - opts.environment = testVars.environment; + opts.endpoint = testVars.endpoint; opts.authUrl = "http://localhost:8982/get-token-request"; - AblyRest ably = new AblyRest(opts); + PubSubHttpClient ably = HttpClientFactory.create(opts); /* make a call to trigger token request */ try { TokenDetails tokenDetails = ably.auth.requestToken(null, null); @@ -371,10 +371,10 @@ public void auth_authURL_tokenrequest() { public void auth_authURL_tokenrequest_post() { try { ClientOptions opts = createOptions(); - opts.environment = testVars.environment; + opts.endpoint = testVars.endpoint; opts.authUrl = "http://localhost:8982/post-token-request"; opts.authMethod = HttpConstants.Methods.POST; - AblyRest ably = new AblyRest(opts); + PubSubHttpClient ably = HttpClientFactory.create(opts); /* make a call to trigger token request */ try { TokenDetails tokenDetails = ably.auth.requestToken(null, null); @@ -398,9 +398,9 @@ public void auth_authURL_tokenrequest_post() { public void auth_authURL_token() { try { ClientOptions opts = createOptions(); - opts.environment = testVars.environment; + opts.endpoint = testVars.endpoint; opts.authUrl = "http://localhost:8982/get-token"; - AblyRest ably = new AblyRest(opts); + PubSubHttpClient ably = HttpClientFactory.create(opts); /* make a call to trigger token request */ try { TokenDetails tokenDetails = ably.auth.requestToken(null, null); @@ -423,9 +423,9 @@ public void auth_authURL_token() { public void auth_authURL_err() { try { ClientOptions opts = createOptions(); - opts.environment = testVars.environment; + opts.endpoint = testVars.endpoint; opts.authUrl = "http://localhost:8982/404"; - AblyRest ably = new AblyRest(opts); + PubSubHttpClient ably = HttpClientFactory.create(opts); /* make a call to trigger token request */ try { ably.auth.requestToken(null, null); @@ -448,10 +448,10 @@ public void auth_authURL_err() { public void auth_authURL_timeout() { try { ClientOptions opts = createOptions(); - opts.environment = testVars.environment; + opts.endpoint = testVars.endpoint; opts.authUrl = "http://localhost:8982/wait?delay=6000"; opts.httpRequestTimeout = 5000; - AblyRest ably = new AblyRest(opts); + PubSubHttpClient ably = HttpClientFactory.create(opts); /* make a call to trigger token request */ try { ably.auth.requestToken(null, null); @@ -481,7 +481,7 @@ public void auth_authURL_authParams_get() { opts.authUrl = "http://localhost:8982/get-token-request"; opts.authParams = new Param[]{new Param("test-param", "test-value")}; - AblyRest ably = new AblyRest(opts); + PubSubHttpClient ably = HttpClientFactory.create(opts); /* make a call to trigger token request */ ably.auth.requestToken(null, null); @@ -509,7 +509,7 @@ public void auth_authURL_authParams_post() { opts.authUrl = "http://localhost:8982/post-token-request"; opts.authMethod = HttpConstants.Methods.POST; opts.authParams = new Param[]{new Param("test-param", "test-value")}; - AblyRest ably = new AblyRest(opts); + PubSubHttpClient ably = HttpClientFactory.create(opts); /* make a call to trigger token request */ ably.auth.requestToken(null, null); @@ -539,7 +539,7 @@ public void auth_authURL_urlParams_get() { opts.httpListener = httpListener; opts.authUrl = "http://localhost:8982/get-token-request?test-param=test-value"; - AblyRest ably = new AblyRest(opts); + PubSubHttpClient ably = HttpClientFactory.create(opts); /* make a call to trigger token request */ ably.auth.requestToken(null, null); @@ -566,7 +566,7 @@ public void auth_authURL_urlParams_post() { opts.authUrl = "http://localhost:8982/post-token-request?test-param=test-value"; opts.authMethod = HttpConstants.Methods.POST; - AblyRest ably = new AblyRest(opts); + PubSubHttpClient ably = HttpClientFactory.create(opts); /* make a call to trigger token request */ ably.auth.requestToken(null, null); @@ -593,7 +593,7 @@ public void auth_authURL_urlParams_get_conflict() { opts.authUrl = "http://localhost:8982/get-token-request?test-param=test-value-urlParam"; opts.authParams = new Param[]{new Param("test-param", "test-value-authParam")}; - AblyRest ably = new AblyRest(opts); + PubSubHttpClient ably = HttpClientFactory.create(opts); /* make a call to trigger token request */ ably.auth.requestToken(null, null); @@ -620,7 +620,7 @@ public void auth_authURL_authParams_get_conflict() { opts.authUrl = "http://localhost:8982/get-token-request"; opts.authParams = new Param[]{new Param("ttl", "500")}; - AblyRest ably = new AblyRest(opts); + PubSubHttpClient ably = HttpClientFactory.create(opts); /* make a call to trigger token request */ ably.auth.requestToken(new TokenParams() {{ @@ -649,7 +649,7 @@ public void auth_authURL_authHeaders_get() { opts.authUrl = "http://localhost:8982/get-token-request"; opts.authHeaders = new Param[]{new Param("test-header", "test-value")}; - AblyRest ably = new AblyRest(opts); + PubSubHttpClient ably = HttpClientFactory.create(opts); /* make a call to trigger token request */ ably.auth.requestToken(null, null); @@ -677,7 +677,7 @@ public void auth_authURL_authHeaders_post() { opts.authUrl = "http://localhost:8982/get-token-request"; opts.authHeaders = new Param[]{new Param("test-header", "test-value")}; - AblyRest ably = new AblyRest(opts); + PubSubHttpClient ably = HttpClientFactory.create(opts); /* make a call to trigger token request */ ably.auth.requestToken(null, null); @@ -700,7 +700,7 @@ public void auth_authcallback_tokenrequest() { try { /* implement callback, using Ably instance with key */ TokenCallback authCallback = new TokenCallback() { - private AblyRest ably = new AblyRest(createOptions(testVars.keys[0].keyStr)); + private PubSubHttpClient ably = HttpClientFactory.create(createOptions(testVars.keys[0].keyStr)); @Override public Object getTokenRequest(TokenParams params) throws AblyException { return ably.auth.createTokenRequest(params, null); @@ -710,7 +710,7 @@ public Object getTokenRequest(TokenParams params) throws AblyException { /* create Ably instance without key */ ClientOptions opts = createOptions(); opts.authCallback = authCallback; - AblyRest ably = new AblyRest(opts); + PubSubHttpClient ably = HttpClientFactory.create(opts); /* make a call to trigger token request */ try { @@ -735,7 +735,7 @@ public void auth_authcallback_tokendetails() { try { /* implement callback, using Ably instance with key */ TokenCallback authCallback = new TokenCallback() { - private AblyRest ably = new AblyRest(createOptions(testVars.keys[0].keyStr)); + private PubSubHttpClient ably = HttpClientFactory.create(createOptions(testVars.keys[0].keyStr)); @Override public Object getTokenRequest(TokenParams params) throws AblyException { return ably.auth.requestToken(params, null); @@ -745,7 +745,7 @@ public Object getTokenRequest(TokenParams params) throws AblyException { /* create Ably instance without key */ ClientOptions opts = createOptions(); opts.authCallback = authCallback; - AblyRest ably = new AblyRest(opts); + PubSubHttpClient ably = HttpClientFactory.create(opts); /* make a call to trigger token request */ try { @@ -769,7 +769,7 @@ public Object getTokenRequest(TokenParams params) throws AblyException { public void auth_authcallback_tokenstring() throws AblyException { /* implement callback, using Ably instance with key */ TokenCallback authCallback = new TokenCallback() { - private AblyRest ably = new AblyRest(createOptions(testVars.keys[0].keyStr)); + private PubSubHttpClient ably = HttpClientFactory.create(createOptions(testVars.keys[0].keyStr)); @Override public Object getTokenRequest(TokenParams params) throws AblyException { return ably.auth.requestToken(params, null).token; @@ -779,7 +779,7 @@ public Object getTokenRequest(TokenParams params) throws AblyException { /* create Ably instance without key */ ClientOptions opts = createOptions(); opts.authCallback = authCallback; - AblyRest ably = new AblyRest(opts); + PubSubHttpClient ably = HttpClientFactory.create(opts); /* make a call to trigger token request */ try { @@ -798,7 +798,7 @@ public Object getTokenRequest(TokenParams params) throws AblyException { public void auth_authcallback_token_expire() { try { ClientOptions optsForToken = createOptions(testVars.keys[0].keyStr); - final AblyRest ablyForToken = new AblyRest(optsForToken); + final PubSubHttpClient ablyForToken = HttpClientFactory.create(optsForToken); TokenDetails tokenDetails = ablyForToken.auth.requestToken(new TokenParams() {{ ttl = 5000L; }}, null); assertNotNull("Expected token value", tokenDetails.token); @@ -819,7 +819,7 @@ public Object getTokenRequest(TokenParams params) throws AblyException { ClientOptions opts = createOptions(); opts.token = tokenDetails.token; opts.authCallback = authCallback; - AblyRest ably = new AblyRest(opts); + PubSubHttpClient ably = HttpClientFactory.create(opts); /* wait until token expires */ try { @@ -853,7 +853,7 @@ public void auth_authcallback_key_expire() { opts.clientId = "testClientId"; opts.useTokenAuth = true; opts.defaultTokenParams.ttl = 5000L; - AblyRest ably = new AblyRest(opts); + PubSubHttpClient ably = HttpClientFactory.create(opts); /* make a request that relies on the token */ System.out.println("auth_authcallback_key_expire: making first request"); @@ -906,7 +906,7 @@ public Object getTokenRequest(TokenParams params) throws AblyException { /* create Ably instance without key */ ClientOptions opts = createOptions(); opts.authCallback = authCallback; - AblyRest ably = new AblyRest(opts); + PubSubHttpClient ably = HttpClientFactory.create(opts); /* make a call to trigger token request */ try { @@ -930,7 +930,7 @@ public Object getTokenRequest(TokenParams params) throws AblyException { public void authinit_no_auth() { try { ClientOptions opts = new ClientOptions(); - new AblyRest(opts); + HttpClientFactory.create(opts); fail("authinit_no_auth: Unexpected success instantiating library"); } catch (AblyException e) { assertEquals("Verify exception thrown initialising library", e.errorInfo.code, 40000); @@ -948,7 +948,7 @@ public void auth_preemptive_auth_basic() { fillInOptions(opts); RawHttpTracker httpListener = new RawHttpTracker(); opts.httpListener = httpListener; - AblyRest ably = new AblyRest(opts); + PubSubHttpClient ably = HttpClientFactory.create(opts); /* make a request that relies on authentication */ try { @@ -975,7 +975,7 @@ public void auth_preemptive_auth_given_token() { try { ClientOptions optsForToken = createOptions(testVars.keys[0].keyStr); optsForToken.clientId = "testClientId"; - AblyRest ablyForToken = new AblyRest(optsForToken); + PubSubHttpClient ablyForToken = HttpClientFactory.create(optsForToken); TokenDetails tokenDetails = ablyForToken.auth.requestToken(null, null); /* create Ably instance with token */ @@ -983,7 +983,7 @@ public void auth_preemptive_auth_given_token() { fillInOptions(opts); RawHttpTracker httpListener = new RawHttpTracker(); opts.httpListener = httpListener; - AblyRest ably = new AblyRest(opts); + PubSubHttpClient ably = HttpClientFactory.create(opts); /* make a request that relies on authentication */ try { @@ -1015,7 +1015,7 @@ public void auth_preemptive_auth_created_token() { opts.useTokenAuth = true; RawHttpTracker httpListener = new RawHttpTracker(); opts.httpListener = httpListener; - AblyRest ably = new AblyRest(opts); + PubSubHttpClient ably = HttpClientFactory.create(opts); /* make a request that relies on authentication */ try { @@ -1044,7 +1044,7 @@ public void auth_client_wildcard() { try { opts = createOptions(); opts.clientId = "*"; - new AblyRest(opts); + HttpClientFactory.create(opts); } catch (AblyException e) { assertEquals("Verify exception raised from disallowed wildcard clientId", e.errorInfo.code, 40000); } @@ -1068,7 +1068,7 @@ public void auth_client_match_token() { opts = createOptions(); opts.tokenDetails = tokenDetails; opts.clientId = "options clientId"; - new AblyRest(opts); + HttpClientFactory.create(opts); } catch (AblyException e) { assertEquals("Verify exception raised from incompatible clientIds", e.errorInfo.code, 40101); } @@ -1093,7 +1093,7 @@ public void auth_client_match_token_wildcard() { opts = createOptions(); opts.tokenDetails = tokenDetails; opts.clientId = "options clientId"; - AblyRest ably = new AblyRest(opts); + PubSubHttpClient ably = HttpClientFactory.create(opts); assertEquals("Verify given clientId is compatible with wildcard token clientId", ably.auth.clientId, "options clientId"); } catch (AblyException e) { e.printStackTrace(); @@ -1118,7 +1118,7 @@ public void auth_client_null_match_token_wildcard() { opts = createOptions(); opts.tokenDetails = tokenDetails; opts.clientId = null; - AblyRest ably = new AblyRest(opts); + PubSubHttpClient ably = HttpClientFactory.create(opts); assertEquals("Verify given clientId is compatible with wildcard token clientId", ably.auth.clientId, "*"); } catch (AblyException e) { e.printStackTrace(); @@ -1137,7 +1137,7 @@ public void auth_clientid_null_success() { try { /* implement callback, using Ably instance with key */ TokenCallback authCallback = new TokenCallback() { - private AblyRest ably = new AblyRest(createOptions(testVars.keys[0].keyStr)); + private PubSubHttpClient ably = HttpClientFactory.create(createOptions(testVars.keys[0].keyStr)); @Override public Object getTokenRequest(TokenParams params) throws AblyException { return ably.auth.requestToken(params, null); @@ -1148,7 +1148,7 @@ public Object getTokenRequest(TokenParams params) throws AblyException { ClientOptions options = createOptions(); options.clientId = null; options.authCallback = authCallback; - AblyRest ably = new AblyRest(options); + PubSubHttpClient ably = HttpClientFactory.create(options); /* Fetch token */ TokenDetails tokenDetails = ably.auth.requestToken(null, null); @@ -1194,12 +1194,12 @@ public Object getTokenRequest(TokenParams params) throws AblyException { */ @Test public void auth_clientid_null_mismatch() throws AblyException { - AblyRest ably = null; + PubSubHttpClient ably = null; try { /* implement callback, using Ably instance with key */ TokenCallback authCallback = new TokenCallback() { - private AblyRest ably = new AblyRest(createOptions(testVars.keys[0].keyStr)); + private PubSubHttpClient ably = HttpClientFactory.create(createOptions(testVars.keys[0].keyStr)); @Override public Object getTokenRequest(TokenParams params) throws AblyException { return ably.auth.requestToken(params, null); @@ -1209,7 +1209,7 @@ public Object getTokenRequest(TokenParams params) throws AblyException { /* create Ably instance */ ClientOptions options = createOptions(); options.authCallback = authCallback; - ably = new AblyRest(options); + ably = HttpClientFactory.create(options); /* Create token with null clientId */ TokenParams tokenParams = new TokenParams() {{ clientId = null; }}; @@ -1246,7 +1246,7 @@ public void auth_clientid_null_wildcard () { try { /* implement callback, using Ably instance with key */ TokenCallback authCallback = new TokenCallback() { - private AblyRest ably = new AblyRest(createOptions(testVars.keys[0].keyStr)); + private PubSubHttpClient ably = HttpClientFactory.create(createOptions(testVars.keys[0].keyStr)); @Override public Object getTokenRequest(TokenParams params) throws AblyException { params.clientId = "*"; @@ -1257,7 +1257,7 @@ public Object getTokenRequest(TokenParams params) throws AblyException { /* create Ably instance with wildcard clientId */ ClientOptions options = createOptions(); options.authCallback = authCallback; - AblyRest ably = new AblyRest(options); + PubSubHttpClient ably = HttpClientFactory.create(options); /* Fetch token */ TokenDetails tokenDetails = ably.auth.authorize(null, null); @@ -1306,7 +1306,7 @@ public void auth_clientid_explicit_wildcard () { try { /* implement callback, using Ably instance with key */ TokenCallback authCallback = new TokenCallback() { - private AblyRest ably = new AblyRest(createOptions(testVars.keys[0].keyStr)); + private PubSubHttpClient ably = HttpClientFactory.create(createOptions(testVars.keys[0].keyStr)); @Override public Object getTokenRequest(TokenParams params) throws AblyException { params.clientId = "*"; @@ -1317,7 +1317,7 @@ public Object getTokenRequest(TokenParams params) throws AblyException { /* create Ably instance with wildcard clientId */ ClientOptions options = createOptions(); options.authCallback = authCallback; - AblyRest ably = new AblyRest(options); + PubSubHttpClient ably = HttpClientFactory.create(options); /* Fetch token */ TokenDetails tokenDetails = ably.auth.authorize(null, null); @@ -1369,7 +1369,7 @@ public void auth_clientid_publish_implicit() { String clientId = "test clientId"; ClientOptions optsForToken = createOptions(testVars.keys[0].keyStr); optsForToken.clientId = clientId; - AblyRest ablyForToken = new AblyRest(optsForToken); + PubSubHttpClient ablyForToken = HttpClientFactory.create(optsForToken); TokenDetails tokenDetails = ablyForToken.auth.requestToken(null, null); final Message[] messages = new Message[1]; @@ -1402,7 +1402,7 @@ public void onRawHttpException(String id, String method, Throwable t) {} }}; fillInOptions(options); options.tokenDetails = tokenDetails; - AblyRest ably = new AblyRest(options); + PubSubHttpClient ably = HttpClientFactory.create(options); /* Publish a message */ Message messagePublishee = new Message( @@ -1432,7 +1432,7 @@ public void auth_clientid_publish_explicit_in_message() { try { final String messageClientId = "test clientId"; ClientOptions optsForToken = createOptions(testVars.keys[0].keyStr); - AblyRest ablyForToken = new AblyRest(optsForToken); + PubSubHttpClient ablyForToken = HttpClientFactory.create(optsForToken); TokenDetails tokenDetails = ablyForToken.auth.requestToken(new TokenParams() {{ this.clientId = "*"; }}, null); @@ -1467,7 +1467,7 @@ public void onRawHttpException(String id, String method, Throwable t) {} }}; fillInOptions(options); options.tokenDetails = tokenDetails; - AblyRest ably = new AblyRest(options); + PubSubHttpClient ably = HttpClientFactory.create(options); /* Publish a message */ Message messagePublishee = new Message( @@ -1499,7 +1499,7 @@ public void auth_clientid_basic_null_wildcard() { try { /* create Ably instance with basic auth and no clientId */ ClientOptions options = createOptions(testVars.keys[0].keyStr); - AblyRest ably = new AblyRest(options); + PubSubHttpClient ably = HttpClientFactory.create(options); /* Publish message */ String messageName = "wildcard"; @@ -1548,7 +1548,7 @@ public void auth_clientid_in_defaultparams() { ClientOptions options = createOptions(testVars.keys[0].keyStr); options.useTokenAuth = true; options.defaultTokenParams = new TokenParams() {{ this.clientId = defaultClientId; }}; - AblyRest ably = new AblyRest(options); + PubSubHttpClient ably = HttpClientFactory.create(options); /* get a token with these default params */ ably.auth.authorize(null, null); @@ -1578,7 +1578,7 @@ public void auth_clientid_in_opts_overrides_defaultparams() { options.useTokenAuth = true; options.clientId = clientId; options.defaultTokenParams = new TokenParams() {{ this.clientId = defaultClientId; }}; - AblyRest ably = new AblyRest(options); + PubSubHttpClient ably = HttpClientFactory.create(options); /* get a token with these default params */ ably.auth.authorize(null, null); @@ -1600,7 +1600,7 @@ public void auth_useTokenAuth() { try { ClientOptions opts = createOptions(testVars.keys[0].keyStr); opts.useTokenAuth = true; - AblyRest ably = new AblyRest(opts); + PubSubHttpClient ably = HttpClientFactory.create(opts); /* verify that we don't have a token yet. */ assertTrue("Not expecting a token yet", ably.auth.getTokenDetails() == null); /* make a request that relies on the token */ @@ -1630,15 +1630,15 @@ public void auth_testQueryTime() { nanoHTTPD.clearRequestHistory(); ClientOptions opts = new ClientOptions(testVars.keys[0].keyStr); opts.tls = false; - opts.restHost = "localhost"; + opts.endpoint = "localhost"; opts.port = nanoHTTPD.getListeningPort(); opts.queryTime = true; - AblyRest ably1 = new AblyRest(opts); + PubSubHttpClient ably1 = HttpClientFactory.create(opts); @SuppressWarnings("unused") Auth.TokenRequest tr1 = ably1.auth.createTokenRequest(null, null); - AblyRest ably2 = new AblyRest(opts); + PubSubHttpClient ably2 = HttpClientFactory.create(opts); @SuppressWarnings("unused") Auth.TokenRequest tr2 = ably2.auth.createTokenRequest(null, null); @@ -1663,12 +1663,12 @@ public void auth_testQueryTime() { @Test public void auth_json_interop() { /* create a token request */ - AblyRest ably; + PubSubHttpClient ably; TokenRequest tokenRequest; try { ClientOptions opts = createOptions(testVars.keys[0].keyStr); opts.clientId = "Test client id"; - ably = new AblyRest(opts); + ably = HttpClientFactory.create(opts); tokenRequest = ably.auth.createTokenRequest(new TokenParams() {{ ttl = 10000; capability = "{\"*\": [\"*\"]}"; @@ -1699,13 +1699,13 @@ public void auth_json_interop() { */ @Test public void auth_token_request_json_omitted_defaults() { - AblyRest ably; + PubSubHttpClient ably; TokenRequest tokenRequest; try { for (final String cap : new String[] {null, ""}) { ClientOptions opts = createOptions(testVars.keys[0].keyStr); opts.clientId = "Test client id"; - ably = new AblyRest(opts); + ably = HttpClientFactory.create(opts); tokenRequest = ably.auth.createTokenRequest(new TokenParams() {{ capability = cap; }}, null); @@ -1730,7 +1730,7 @@ public void auth_renew_token_bearer_auth() { opts.defaultTokenParams = new TokenParams() {{ ttl = 500; }}; - AblyRest ably = new AblyRest(opts); + PubSubHttpClient ably = HttpClientFactory.create(opts); // Any request will issue a new token with the defaultTokenParams and use it. @@ -1742,7 +1742,7 @@ public void auth_renew_token_bearer_auth() { Thread.sleep(1000); ClientOptions optsWithOldToken = createOptions(); optsWithOldToken.tokenDetails = oldToken; - AblyRest ablyWithOldToken = new AblyRest(optsWithOldToken); + PubSubHttpClient ablyWithOldToken = HttpClientFactory.create(optsWithOldToken); try { ablyWithOldToken.channels.get("test").history(null); fail("expected old token to be expired already"); @@ -1772,7 +1772,7 @@ public void auth_local_token_expiry_check_sync() { final String testKey = testVars.keys[0].keyStr; ClientOptions optsForToken = createOptions(testKey); optsForToken.queryTime = true; - AblyRest ablyForToken = new AblyRest(optsForToken); + PubSubHttpClient ablyForToken = HttpClientFactory.create(optsForToken); TokenDetails tokenDetails = ablyForToken.auth.requestToken(new TokenParams(){{ ttl = 100L; }}, null); @@ -1783,7 +1783,7 @@ public void auth_local_token_expiry_check_sync() { opts.tokenDetails = tokenDetails; RawHttpTracker httpListener = new RawHttpTracker(); opts.httpListener = httpListener; - AblyRest ably = new AblyRest(opts); + PubSubHttpClient ably = HttpClientFactory.create(opts); /* sync this library instance to server by creating a token request */ ably.auth.createTokenRequest(null, new Auth.AuthOptions() {{ key = testKey; queryTime = true; }}); @@ -1820,7 +1820,7 @@ public void auth_local_token_expiry_check_nosync() { final String testKey = testVars.keys[0].keyStr; ClientOptions optsForToken = createOptions(testKey); optsForToken.queryTime = true; - AblyRest ablyForToken = new AblyRest(optsForToken); + PubSubHttpClient ablyForToken = HttpClientFactory.create(optsForToken); TokenDetails tokenDetails = ablyForToken.auth.requestToken(new TokenParams(){{ ttl = 100L; }}, null); @@ -1831,7 +1831,7 @@ public void auth_local_token_expiry_check_nosync() { opts.tokenDetails = tokenDetails; RawHttpTracker httpListener = new RawHttpTracker(); opts.httpListener = httpListener; - AblyRest ably = new AblyRest(opts); + PubSubHttpClient ably = HttpClientFactory.create(opts); /* wait for the token to expire */ try { Thread.sleep(200L); } catch(InterruptedException ie) {} @@ -1864,7 +1864,7 @@ public void auth_local_token_expiry_check_nosync_retried() { final String testKey = testVars.keys[0].keyStr; ClientOptions optsForToken = createOptions(testKey); optsForToken.queryTime = false; - final AblyRest ablyForToken = new AblyRest(optsForToken); + final PubSubHttpClient ablyForToken = HttpClientFactory.create(optsForToken); TokenDetails tokenDetails = ablyForToken.auth.requestToken(new TokenParams(){{ ttl = 100L; }}, null); @@ -1882,7 +1882,7 @@ public Object getTokenRequest(TokenParams params) throws AblyException { RawHttpTracker httpListener = new RawHttpTracker(); opts.httpListener = httpListener; - AblyRest ably = new AblyRest(opts); + PubSubHttpClient ably = HttpClientFactory.create(opts); /* wait for the token to expire */ try { Thread.sleep(200L); } catch(InterruptedException ie) {} diff --git a/lib/src/test/java/io/ably/lib/test/rest/RestCapabilityTest.java b/lib/src/test/java/io/ably/pubsub/test/http/HttpCapabilityTest.java similarity index 94% rename from lib/src/test/java/io/ably/lib/test/rest/RestCapabilityTest.java rename to lib/src/test/java/io/ably/pubsub/test/http/HttpCapabilityTest.java index 312f59c7c..ce8a19f75 100644 --- a/lib/src/test/java/io/ably/lib/test/rest/RestCapabilityTest.java +++ b/lib/src/test/java/io/ably/pubsub/test/http/HttpCapabilityTest.java @@ -1,4 +1,4 @@ -package io.ably.lib.test.rest; +package io.ably.pubsub.test.http; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; @@ -7,24 +7,25 @@ import org.junit.Before; import org.junit.Test; -import io.ably.lib.rest.AblyRest; -import io.ably.lib.rest.Auth.AuthOptions; -import io.ably.lib.rest.Auth.TokenDetails; -import io.ably.lib.rest.Auth.TokenParams; -import io.ably.lib.test.common.ParameterizedTest; -import io.ably.lib.test.common.Setup.Key; -import io.ably.lib.types.AblyException; -import io.ably.lib.types.Capability; -import io.ably.lib.types.ClientOptions; +import io.ably.pubsub.http.HttpClientFactory; +import io.ably.pubsub.http.PubSubHttpClient; +import io.ably.pubsub.http.Auth.AuthOptions; +import io.ably.pubsub.http.Auth.TokenDetails; +import io.ably.pubsub.http.Auth.TokenParams; +import io.ably.pubsub.test.common.ParameterizedTest; +import io.ably.pubsub.test.common.Setup.Key; +import io.ably.pubsub.types.AblyException; +import io.ably.pubsub.types.Capability; +import io.ably.pubsub.types.ClientOptions; -public class RestCapabilityTest extends ParameterizedTest { +public class HttpCapabilityTest extends ParameterizedTest { - private AblyRest ably; + private PubSubHttpClient ably; @Before public void setUpBefore() throws Exception { ClientOptions opts = createOptions(testVars.keys[0].keyStr); - ably = new AblyRest(opts); + ably = HttpClientFactory.create(opts); } /** diff --git a/lib/src/test/java/io/ably/lib/test/rest/RestChannelBulkPublishTest.java b/lib/src/test/java/io/ably/pubsub/test/http/HttpChannelBulkPublishTest.java similarity index 90% rename from lib/src/test/java/io/ably/lib/test/rest/RestChannelBulkPublishTest.java rename to lib/src/test/java/io/ably/pubsub/test/http/HttpChannelBulkPublishTest.java index 5b1e9778a..09192c577 100644 --- a/lib/src/test/java/io/ably/lib/test/rest/RestChannelBulkPublishTest.java +++ b/lib/src/test/java/io/ably/pubsub/test/http/HttpChannelBulkPublishTest.java @@ -1,18 +1,20 @@ -package io.ably.lib.test.rest; +package io.ably.pubsub.test.http; -import io.ably.lib.realtime.AblyRealtime; -import io.ably.lib.realtime.Channel; -import io.ably.lib.realtime.ChannelState; -import io.ably.lib.rest.AblyRest; -import io.ably.lib.test.common.Helpers.ChannelWaiter; -import io.ably.lib.test.common.Helpers.MessageWaiter; -import io.ably.lib.test.common.ParameterizedTest; -import io.ably.lib.types.AblyException; -import io.ably.lib.types.ClientOptions; -import io.ably.lib.types.Message; -import io.ably.lib.types.PaginatedResult; -import io.ably.lib.types.Param; -import io.ably.lib.types.PublishResponse; +import io.ably.pubsub.realtime.PubSubRealtimeClient; +import io.ably.pubsub.realtime.RealtimeClientFactory; +import io.ably.pubsub.realtime.Channel; +import io.ably.pubsub.realtime.ChannelState; +import io.ably.pubsub.http.HttpClientFactory; +import io.ably.pubsub.http.PubSubHttpClient; +import io.ably.pubsub.test.common.Helpers.ChannelWaiter; +import io.ably.pubsub.test.common.Helpers.MessageWaiter; +import io.ably.pubsub.test.common.ParameterizedTest; +import io.ably.pubsub.types.AblyException; +import io.ably.pubsub.types.ClientOptions; +import io.ably.pubsub.types.Message; +import io.ably.pubsub.types.PaginatedResult; +import io.ably.pubsub.types.Param; +import io.ably.pubsub.types.PublishResponse; import org.junit.Ignore; import org.junit.Test; @@ -26,7 +28,7 @@ import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; -public class RestChannelBulkPublishTest extends ParameterizedTest { +public class HttpChannelBulkPublishTest extends ParameterizedTest { /** * Publish a single message on multiple channels @@ -46,7 +48,7 @@ public void bulk_publish_multiple_channels_simple() { try { /* setup library instance */ ClientOptions opts = createOptions(testVars.keys[0].keyStr); - AblyRest ably = new AblyRest(opts); + PubSubHttpClient ably = HttpClientFactory.create(opts); /* first, publish some messages */ int channelCount = 5; @@ -86,12 +88,12 @@ public void bulk_publish_multiple_channels_simple() { */ @Test public void bulk_publish_multiple_channels_param() { - AblyRealtime rxAbly = null; + PubSubRealtimeClient rxAbly = null; try { /* setup library instance */ ClientOptions opts = createOptions(testVars.keys[0].keyStr); - AblyRest ably = new AblyRest(opts); - rxAbly = new AblyRealtime(opts); + PubSubHttpClient ably = HttpClientFactory.create(opts); + rxAbly = RealtimeClientFactory.create(opts); /* first, publish some messages */ int channelCount = 5; @@ -172,7 +174,7 @@ public void bulk_publish_multiple_channels_multiple_messages() { /* setup library instance */ ClientOptions opts = createOptions(testVars.keys[0].keyStr); opts.idempotentRestPublishing = true; - AblyRest ably = new AblyRest(opts); + PubSubHttpClient ably = HttpClientFactory.create(opts); /* first, publish some messages */ int channelCount = 5; @@ -240,7 +242,7 @@ public void bulk_publish_multiple_channels_partial_error() { try { /* setup library instance */ ClientOptions opts = createOptions(testVars.keys[6].keyStr); - AblyRest ably = new AblyRest(opts); + PubSubHttpClient ably = HttpClientFactory.create(opts); /* first, publish some messages */ String baseChannelName = "persisted:" + testParams.name + ":channel"; diff --git a/lib/src/test/java/io/ably/lib/test/rest/RestChannelHistoryTest.java b/lib/src/test/java/io/ably/pubsub/test/http/HttpChannelHistoryTest.java similarity index 97% rename from lib/src/test/java/io/ably/lib/test/rest/RestChannelHistoryTest.java rename to lib/src/test/java/io/ably/pubsub/test/http/HttpChannelHistoryTest.java index e54fb0a23..0407ddac1 100644 --- a/lib/src/test/java/io/ably/lib/test/rest/RestChannelHistoryTest.java +++ b/lib/src/test/java/io/ably/pubsub/test/http/HttpChannelHistoryTest.java @@ -1,4 +1,4 @@ -package io.ably.lib.test.rest; +package io.ably.pubsub.test.http; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; @@ -14,18 +14,19 @@ import org.junit.Test; import org.junit.rules.Timeout; -import io.ably.lib.rest.AblyRest; -import io.ably.lib.rest.Channel; -import io.ably.lib.test.common.ParameterizedTest; -import io.ably.lib.types.AblyException; -import io.ably.lib.types.ClientOptions; -import io.ably.lib.types.Message; -import io.ably.lib.types.PaginatedResult; -import io.ably.lib.types.Param; +import io.ably.pubsub.http.HttpClientFactory; +import io.ably.pubsub.http.PubSubHttpClient; +import io.ably.pubsub.http.Channel; +import io.ably.pubsub.test.common.ParameterizedTest; +import io.ably.pubsub.types.AblyException; +import io.ably.pubsub.types.ClientOptions; +import io.ably.pubsub.types.Message; +import io.ably.pubsub.types.PaginatedResult; +import io.ably.pubsub.types.Param; -public class RestChannelHistoryTest extends ParameterizedTest { +public class HttpChannelHistoryTest extends ParameterizedTest { - private AblyRest ably; + private PubSubHttpClient ably; private long timeOffset; @Rule @@ -35,7 +36,7 @@ public class RestChannelHistoryTest extends ParameterizedTest { public void setUpBefore() throws Exception { ClientOptions opts = createOptions(testVars.keys[0].keyStr); opts.useBinaryProtocol = false; - ably = new AblyRest(opts); + ably = HttpClientFactory.create(opts); long timeFromService = ably.time(); timeOffset = timeFromService - System.currentTimeMillis(); } diff --git a/lib/src/test/java/io/ably/lib/test/rest/RestChannelMessageEditTest.java b/lib/src/test/java/io/ably/pubsub/test/http/HttpChannelMessageEditTest.java similarity index 95% rename from lib/src/test/java/io/ably/lib/test/rest/RestChannelMessageEditTest.java rename to lib/src/test/java/io/ably/pubsub/test/http/HttpChannelMessageEditTest.java index bdfab7fcc..765e24e65 100644 --- a/lib/src/test/java/io/ably/lib/test/rest/RestChannelMessageEditTest.java +++ b/lib/src/test/java/io/ably/pubsub/test/http/HttpChannelMessageEditTest.java @@ -1,22 +1,23 @@ -package io.ably.lib.test.rest; - -import io.ably.lib.network.EngineType; -import io.ably.lib.network.HttpEngineFactory; -import io.ably.lib.rest.AblyRest; -import io.ably.lib.rest.Channel; -import io.ably.lib.test.common.Helpers; -import io.ably.lib.test.common.ParameterizedTest; -import io.ably.lib.types.AblyException; -import io.ably.lib.types.ChannelOptions; -import io.ably.lib.types.ClientOptions; -import io.ably.lib.types.Message; -import io.ably.lib.types.MessageAction; -import io.ably.lib.types.MessageOperation; -import io.ably.lib.types.PaginatedResult; -import io.ably.lib.types.Param; -import io.ably.lib.types.PublishResult; -import io.ably.lib.types.UpdateDeleteResult; -import io.ably.lib.util.Crypto; +package io.ably.pubsub.test.http; + +import io.ably.pubsub.network.EngineType; +import io.ably.pubsub.network.HttpEngineFactory; +import io.ably.pubsub.http.HttpClientFactory; +import io.ably.pubsub.http.PubSubHttpClient; +import io.ably.pubsub.http.Channel; +import io.ably.pubsub.test.common.Helpers; +import io.ably.pubsub.test.common.ParameterizedTest; +import io.ably.pubsub.types.AblyException; +import io.ably.pubsub.types.ChannelOptions; +import io.ably.pubsub.types.ClientOptions; +import io.ably.pubsub.types.Message; +import io.ably.pubsub.types.MessageAction; +import io.ably.pubsub.types.MessageOperation; +import io.ably.pubsub.types.PaginatedResult; +import io.ably.pubsub.types.Param; +import io.ably.pubsub.types.PublishResult; +import io.ably.pubsub.types.UpdateDeleteResult; +import io.ably.pubsub.util.Crypto; import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -34,17 +35,17 @@ /** * Tests for REST channel message edit and delete operations */ -public class RestChannelMessageEditTest extends ParameterizedTest { +public class HttpChannelMessageEditTest extends ParameterizedTest { @Rule public Timeout testTimeout = Timeout.seconds(300); - private AblyRest ably; + private PubSubHttpClient ably; private EngineType engineType; @Before public void setUpBefore() throws Exception { ClientOptions opts = createOptions(testVars.keys[0].keyStr); - ably = new AblyRest(opts); + ably = HttpClientFactory.create(opts); engineType = HttpEngineFactory.getFirstAvailable().getEngineType(); } diff --git a/lib/src/test/java/io/ably/lib/test/rest/RestChannelPublishTest.java b/lib/src/test/java/io/ably/pubsub/test/http/HttpChannelPublishTest.java similarity index 91% rename from lib/src/test/java/io/ably/lib/test/rest/RestChannelPublishTest.java rename to lib/src/test/java/io/ably/pubsub/test/http/HttpChannelPublishTest.java index 59f9c709f..364c4b880 100644 --- a/lib/src/test/java/io/ably/lib/test/rest/RestChannelPublishTest.java +++ b/lib/src/test/java/io/ably/pubsub/test/http/HttpChannelPublishTest.java @@ -1,22 +1,23 @@ -package io.ably.lib.test.rest; - -import io.ably.lib.debug.DebugOptions; -import io.ably.lib.http.HttpCore; -import io.ably.lib.network.HttpRequest; -import io.ably.lib.rest.AblyRest; -import io.ably.lib.rest.Auth; -import io.ably.lib.rest.Channel; -import io.ably.lib.test.common.Helpers.AsyncWaiter; -import io.ably.lib.test.common.Helpers.CompletionSet; -import io.ably.lib.test.common.ParameterizedTest; -import io.ably.lib.types.AblyException; -import io.ably.lib.types.AsyncPaginatedResult; -import io.ably.lib.types.ClientOptions; -import io.ably.lib.types.ErrorInfo; -import io.ably.lib.types.Message; -import io.ably.lib.types.MessageSerializer; -import io.ably.lib.types.PaginatedResult; -import io.ably.lib.types.Param; +package io.ably.pubsub.test.http; + +import io.ably.pubsub.debug.DebugOptions; +import io.ably.pubsub.http.HttpCore; +import io.ably.pubsub.network.HttpRequest; +import io.ably.pubsub.http.HttpClientFactory; +import io.ably.pubsub.http.PubSubHttpClient; +import io.ably.pubsub.http.Auth; +import io.ably.pubsub.http.Channel; +import io.ably.pubsub.test.common.Helpers.AsyncWaiter; +import io.ably.pubsub.test.common.Helpers.CompletionSet; +import io.ably.pubsub.test.common.ParameterizedTest; +import io.ably.pubsub.types.AblyException; +import io.ably.pubsub.types.AsyncPaginatedResult; +import io.ably.pubsub.types.ClientOptions; +import io.ably.pubsub.types.ErrorInfo; +import io.ably.pubsub.types.Message; +import io.ably.pubsub.types.MessageSerializer; +import io.ably.pubsub.types.PaginatedResult; +import io.ably.pubsub.types.Param; import org.junit.Before; import org.junit.Test; @@ -32,14 +33,14 @@ import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; -public class RestChannelPublishTest extends ParameterizedTest { +public class HttpChannelPublishTest extends ParameterizedTest { - private AblyRest ably; + private PubSubHttpClient ably; @Before public void setUpBefore() throws Exception { ClientOptions opts = createOptions(testVars.keys[0].keyStr); - ably = new AblyRest(opts); + ably = HttpClientFactory.create(opts); } /** @@ -154,7 +155,7 @@ public void onRawHttpResponse(String id, String method, HttpCore.Response respon @Override public void onRawHttpException(String id, String method, Throwable t) {} }; - AblyRest ably = new AblyRest(opts); + PubSubHttpClient ably = HttpClientFactory.create(opts); /* first, publish messages */ pubChannel = ably.channels.get(channelName); @@ -216,7 +217,7 @@ public void onRawHttpResponse(String id, String method, HttpCore.Response respon @Override public void onRawHttpException(String id, String method, Throwable t) {} }; - AblyRest ably = new AblyRest(opts); + PubSubHttpClient ably = HttpClientFactory.create(opts); /* first, publish messages */ pubChannel = ably.channels.get(channelName); @@ -293,13 +294,13 @@ public void channel_idempotent_publish_client_generated_retried() { try { final ClientOptions optsForToken = createOptions(testVars.keys[0].keyStr); - final AblyRest ablyForToken = new AblyRest(optsForToken); - Auth.AuthOptions restAuthOptions = new Auth.AuthOptions() {{ + final PubSubHttpClient ablyForToken = HttpClientFactory.create(optsForToken); + Auth.AuthOptions httpAuthOptions = new Auth.AuthOptions() {{ key = optsForToken.key; queryTime = true; }}; - Auth.TokenDetails tokenDetails = ablyForToken.auth.requestToken(new Auth.TokenParams() {{ ttl = 8000L; }}, restAuthOptions); + Auth.TokenDetails tokenDetails = ablyForToken.auth.requestToken(new Auth.TokenParams() {{ ttl = 8000L; }}, httpAuthOptions); DebugOptions opts = new DebugOptions(tokenDetails.token); fillInOptions(opts); @@ -307,7 +308,7 @@ public void channel_idempotent_publish_client_generated_retried() { opts.httpListener = requestListener; /* generate a fallback which resolves to the same address, which the library will treat as a different host */ opts.fallbackHosts = new String[]{ablyForToken.httpCore.getPrimaryHost().toUpperCase(Locale.ROOT)}; - AblyRest ably = new AblyRest(opts); + PubSubHttpClient ably = HttpClientFactory.create(opts); /* publish message */ Channel pubChannel = ably.channels.get(channelName); @@ -363,7 +364,7 @@ public void onRawHttpResponse(String id, String method, HttpCore.Response respon @Override public void onRawHttpException(String id, String method, Throwable t) {} }; - AblyRest ably = new AblyRest(opts); + PubSubHttpClient ably = HttpClientFactory.create(opts); /* first, publish messages */ pubChannel = ably.channels.get(channelName); @@ -401,13 +402,13 @@ public void channel_idempotent_publish_library_generated_retried() { try { final ClientOptions optsForToken = createOptions(testVars.keys[0].keyStr); - final AblyRest ablyForToken = new AblyRest(optsForToken); - Auth.AuthOptions restAuthOptions = new Auth.AuthOptions() {{ + final PubSubHttpClient ablyForToken = HttpClientFactory.create(optsForToken); + Auth.AuthOptions httpAuthOptions = new Auth.AuthOptions() {{ key = optsForToken.key; queryTime = true; }}; - Auth.TokenDetails tokenDetails = ablyForToken.auth.requestToken(new Auth.TokenParams() {{ ttl = 8000L; }}, restAuthOptions); + Auth.TokenDetails tokenDetails = ablyForToken.auth.requestToken(new Auth.TokenParams() {{ ttl = 8000L; }}, httpAuthOptions); DebugOptions opts = new DebugOptions(tokenDetails.token); fillInOptions(opts); @@ -416,7 +417,7 @@ public void channel_idempotent_publish_library_generated_retried() { opts.httpListener = requestListener; /* generate a fallback which resolves to the same address, which the library will treat as a different host */ opts.fallbackHosts = new String[]{ablyForToken.httpCore.getPrimaryHost().toUpperCase(Locale.ROOT)}; - AblyRest ably = new AblyRest(opts); + PubSubHttpClient ably = HttpClientFactory.create(opts); /* publish message */ Channel pubChannel = ably.channels.get(channelName); diff --git a/lib/src/test/java/io/ably/pubsub/test/http/HttpChannelTest.java b/lib/src/test/java/io/ably/pubsub/test/http/HttpChannelTest.java new file mode 100644 index 000000000..67ea6c9c4 --- /dev/null +++ b/lib/src/test/java/io/ably/pubsub/test/http/HttpChannelTest.java @@ -0,0 +1,49 @@ +package io.ably.pubsub.test.http; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertTrue; + +import io.ably.pubsub.http.HttpClientFactory; +import io.ably.pubsub.http.PubSubHttpClient; +import io.ably.pubsub.http.Channel; +import io.ably.pubsub.test.common.Setup; +import io.ably.pubsub.types.AblyException; +import io.ably.pubsub.types.ClientOptions; +import org.junit.Test; + +/** + * Test for basic Channel operation not related to publish or history + */ +public class HttpChannelTest { + /** + * Test if ably.channel.get() returns same object if the same name is given + * Tests RTN2, RTN3, RSN3a, RSN4a + */ + @Test + public void channel_object_caching() throws AblyException { + Setup.TestVars testVars = Setup.getTestVars(); + ClientOptions opts = new ClientOptions(testVars.keys[0].keyStr); + PubSubHttpClient pubSubHttpClient = HttpClientFactory.create(opts); + + Channel channel1 = pubSubHttpClient.channels.get("channel_1"); + Channel channel2 = pubSubHttpClient.channels.get("channel_2"); + + Channel channel1_copy = pubSubHttpClient.channels.get("channel_1"); + + assertEquals("Verify channel objects are cached", channel1, channel1_copy); + assertNotEquals("Verify channel objects are different if different names are requested", channel1, channel2); + + /* Test channel enumeration */ + assertEquals("Verify total number of channels", pubSubHttpClient.channels.size(), 2); + assertTrue("Verify there is channel 1 in the list", pubSubHttpClient.channels.containsKey("channel_1")); + assertTrue("Verify there is channel 2 in the list", pubSubHttpClient.channels.containsKey("channel_2")); + for (final Channel channel : pubSubHttpClient.channels.values()) { + assertTrue("Verify correct channels are in the hashmap", + channel == channel1 || channel == channel2); + } + pubSubHttpClient.channels.release("channel_1"); + channel1_copy = pubSubHttpClient.channels.get("channel_1"); + assertNotEquals("Verify channel is re-created after release", channel1, channel1_copy); + } +} diff --git a/lib/src/test/java/io/ably/lib/test/rest/RestClientTest.java b/lib/src/test/java/io/ably/pubsub/test/http/HttpClientTest.java similarity index 83% rename from lib/src/test/java/io/ably/lib/test/rest/RestClientTest.java rename to lib/src/test/java/io/ably/pubsub/test/http/HttpClientTest.java index 34c9624bc..02767973a 100644 --- a/lib/src/test/java/io/ably/lib/test/rest/RestClientTest.java +++ b/lib/src/test/java/io/ably/pubsub/test/http/HttpClientTest.java @@ -1,10 +1,11 @@ -package io.ably.lib.test.rest; - -import io.ably.lib.debug.DebugOptions; -import io.ably.lib.rest.AblyRest; -import io.ably.lib.test.common.Helpers; -import io.ably.lib.test.common.ParameterizedTest; -import io.ably.lib.types.AblyException; +package io.ably.pubsub.test.http; + +import io.ably.pubsub.debug.DebugOptions; +import io.ably.pubsub.http.HttpClientFactory; +import io.ably.pubsub.http.PubSubHttpClient; +import io.ably.pubsub.test.common.Helpers; +import io.ably.pubsub.test.common.ParameterizedTest; +import io.ably.pubsub.types.AblyException; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; @@ -14,7 +15,7 @@ import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; -public class RestClientTest extends ParameterizedTest { +public class HttpClientTest extends ParameterizedTest { @Rule public Timeout testTimeout = Timeout.seconds(30); @@ -35,7 +36,7 @@ public void request_contains_request_id() throws AblyException { opts.httpListener = httpListener; /* disable addRequestIds */ opts.addRequestIds = false; - AblyRest ablyA = new AblyRest(opts); + PubSubHttpClient ablyA = HttpClientFactory.create(opts); ablyA.channels.get("test").publish("foo", "bar"); /* verify client_id is not a part of url query */ @@ -43,7 +44,7 @@ public void request_contains_request_id() throws AblyException { /* enable addRequestIds */ opts.addRequestIds = true; - AblyRest ablyB = new AblyRest(opts); + PubSubHttpClient ablyB = HttpClientFactory.create(opts); ablyB.channels.get("test").publish("foo", "bar"); /* verify client_id is a part of url query */ @@ -62,10 +63,9 @@ public void error_info_contains_request_id() throws AblyException { Helpers.RawHttpTracker httpListener = new Helpers.RawHttpTracker(); opts.httpListener = httpListener; opts.addRequestIds = true; - opts.environment = null; - opts.restHost = ""; + opts.endpoint = "invalid-host1.com"; opts.fallbackHosts = new String[]{"ably.com"}; - AblyRest ably = new AblyRest(opts); + PubSubHttpClient ably = HttpClientFactory.create(opts); try{ ably.channels.get("test").publish("foo", "bar"); @@ -89,10 +89,9 @@ public void request_id_remain_same_retried_fallbacks() throws AblyException { Helpers.RawHttpTracker httpListener = new Helpers.RawHttpTracker(); opts.httpListener = httpListener; opts.addRequestIds = true; - opts.environment = null; - opts.restHost = "invalid-host1.com"; + opts.endpoint = "invalid-host1.com"; opts.fallbackHosts = new String[]{"invalid-host2.com", "invalid-host3.com"}; - AblyRest ably = new AblyRest(opts); + PubSubHttpClient ably = HttpClientFactory.create(opts); try{ ably.channels.get("test").publish("foo", "bar"); diff --git a/lib/src/test/java/io/ably/lib/test/rest/RestCryptoTest.java b/lib/src/test/java/io/ably/pubsub/test/http/HttpCryptoTest.java similarity index 93% rename from lib/src/test/java/io/ably/lib/test/rest/RestCryptoTest.java rename to lib/src/test/java/io/ably/pubsub/test/http/HttpCryptoTest.java index a3ac5e5f0..aebe448d9 100644 --- a/lib/src/test/java/io/ably/lib/test/rest/RestCryptoTest.java +++ b/lib/src/test/java/io/ably/pubsub/test/http/HttpCryptoTest.java @@ -1,4 +1,4 @@ -package io.ably.lib.test.rest; +package io.ably.pubsub.test.http; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; @@ -10,35 +10,36 @@ import javax.crypto.KeyGenerator; -import io.ably.lib.test.common.Helpers; +import io.ably.pubsub.test.common.Helpers; import org.junit.Before; import org.junit.Test; -import io.ably.lib.rest.AblyRest; -import io.ably.lib.rest.Channel; -import io.ably.lib.test.common.ParameterizedTest; -import io.ably.lib.types.AblyException; -import io.ably.lib.types.ChannelOptions; -import io.ably.lib.types.ClientOptions; -import io.ably.lib.types.Message; -import io.ably.lib.types.PaginatedResult; -import io.ably.lib.types.Param; -import io.ably.lib.util.Crypto; -import io.ably.lib.util.Crypto.CipherParams; - -public class RestCryptoTest extends ParameterizedTest { - - private static final String TAG = RestCryptoTest.class.getName(); - private AblyRest ably; - private AblyRest ably_alt; +import io.ably.pubsub.http.HttpClientFactory; +import io.ably.pubsub.http.PubSubHttpClient; +import io.ably.pubsub.http.Channel; +import io.ably.pubsub.test.common.ParameterizedTest; +import io.ably.pubsub.types.AblyException; +import io.ably.pubsub.types.ChannelOptions; +import io.ably.pubsub.types.ClientOptions; +import io.ably.pubsub.types.Message; +import io.ably.pubsub.types.PaginatedResult; +import io.ably.pubsub.types.Param; +import io.ably.pubsub.util.Crypto; +import io.ably.pubsub.util.Crypto.CipherParams; + +public class HttpCryptoTest extends ParameterizedTest { + + private static final String TAG = HttpCryptoTest.class.getName(); + private PubSubHttpClient ably; + private PubSubHttpClient ably_alt; @Before public void setUpBefore() throws Exception { final ClientOptions opts = createOptions(testVars.keys[0].keyStr); - ably = new AblyRest(opts); + ably = HttpClientFactory.create(opts); final ClientOptions opts_alt = createOptions(testVars.keys[0].keyStr); opts_alt.useBinaryProtocol = testParams.useBinaryProtocol; - ably_alt = new AblyRest(opts_alt); + ably_alt = HttpClientFactory.create(opts_alt); } /** diff --git a/lib/src/test/java/io/ably/lib/test/rest/RestErrorTest.java b/lib/src/test/java/io/ably/pubsub/test/http/HttpErrorTest.java similarity index 87% rename from lib/src/test/java/io/ably/lib/test/rest/RestErrorTest.java rename to lib/src/test/java/io/ably/pubsub/test/http/HttpErrorTest.java index 59cf3cdb0..8ce48dc23 100644 --- a/lib/src/test/java/io/ably/lib/test/rest/RestErrorTest.java +++ b/lib/src/test/java/io/ably/pubsub/test/http/HttpErrorTest.java @@ -1,12 +1,13 @@ -package io.ably.lib.test.rest; +package io.ably.pubsub.test.http; import fi.iki.elonen.NanoHTTPD; -import io.ably.lib.rest.AblyRest; -import io.ably.lib.test.common.ParameterizedTest; -import io.ably.lib.types.AblyException; -import io.ably.lib.types.ClientOptions; -import io.ably.lib.types.Param; -import io.ably.lib.util.Log; +import io.ably.pubsub.http.HttpClientFactory; +import io.ably.pubsub.http.PubSubHttpClient; +import io.ably.pubsub.test.common.ParameterizedTest; +import io.ably.pubsub.types.AblyException; +import io.ably.pubsub.types.ClientOptions; +import io.ably.pubsub.types.Param; +import io.ably.pubsub.util.Log; import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test; @@ -18,7 +19,7 @@ import static org.junit.Assert.assertTrue; -public class RestErrorTest extends ParameterizedTest { +public class HttpErrorTest extends ParameterizedTest { private static SessionHandlerNanoHTTPD server; @@ -52,17 +53,16 @@ public void errorHrefWhenPresentInHref() { final Vector logMessages = new Vector(); try { ClientOptions opts = createOptions(testVars.keys[0].keyStr); - opts.environment = null; opts.tls = false; opts.port = server.getListeningPort(); - opts.restHost = "localhost"; + opts.endpoint = "localhost"; opts.logHandler = new Log.LogHandler() { @Override public void println(int severity, String tag, String msg, Throwable tr) { logMessages.add(msg); } }; - AblyRest ably = new AblyRest(opts); + PubSubHttpClient ably = HttpClientFactory.create(opts); /* make a call that will generate an error */ ably.stats(new Param[]{new Param("message", "Test message"), new Param("href", href(12345))}); @@ -81,17 +81,16 @@ public void errorHrefWhenPresentInMessage() { final Vector logMessages = new Vector(); try { ClientOptions opts = createOptions(testVars.keys[0].keyStr); - opts.environment = null; opts.tls = false; opts.port = server.getListeningPort(); - opts.restHost = "localhost"; + opts.endpoint = "localhost"; opts.logHandler = new Log.LogHandler() { @Override public void println(int severity, String tag, String msg, Throwable tr) { logMessages.add(msg); } }; - AblyRest ably = new AblyRest(opts); + PubSubHttpClient ably = HttpClientFactory.create(opts); /* make a call that will generate an error */ ably.stats(new Param[]{new Param("message", "Test message. See " + href(12345))}); @@ -110,17 +109,16 @@ public void errorHrefWhenCodePresent() { final Vector logMessages = new Vector(); try { ClientOptions opts = createOptions(testVars.keys[0].keyStr); - opts.environment = null; opts.tls = false; opts.port = server.getListeningPort(); - opts.restHost = "localhost"; + opts.endpoint = "localhost"; opts.logHandler = new Log.LogHandler() { @Override public void println(int severity, String tag, String msg, Throwable tr) { logMessages.add(msg); } }; - AblyRest ably = new AblyRest(opts); + PubSubHttpClient ably = HttpClientFactory.create(opts); /* make a call that will generate an error */ ably.stats(new Param[]{new Param("message", "Test message"), new Param("code", "12345")}); diff --git a/lib/src/test/java/io/ably/lib/test/rest/HttpHeaderTest.java b/lib/src/test/java/io/ably/pubsub/test/http/HttpHeaderTest.java similarity index 87% rename from lib/src/test/java/io/ably/lib/test/rest/HttpHeaderTest.java rename to lib/src/test/java/io/ably/pubsub/test/http/HttpHeaderTest.java index 14578a03b..97cbce1b1 100644 --- a/lib/src/test/java/io/ably/lib/test/rest/HttpHeaderTest.java +++ b/lib/src/test/java/io/ably/pubsub/test/http/HttpHeaderTest.java @@ -1,11 +1,12 @@ -package io.ably.lib.test.rest; +package io.ably.pubsub.test.http; import fi.iki.elonen.NanoHTTPD; -import io.ably.lib.rest.AblyRest; -import io.ably.lib.rest.Channel; -import io.ably.lib.test.common.ParameterizedTest; -import io.ably.lib.types.AblyException; -import io.ably.lib.types.ClientOptions; +import io.ably.pubsub.http.HttpClientFactory; +import io.ably.pubsub.http.PubSubHttpClient; +import io.ably.pubsub.http.Channel; +import io.ably.pubsub.test.common.ParameterizedTest; +import io.ably.pubsub.types.AblyException; +import io.ably.pubsub.types.ClientOptions; import org.junit.AfterClass; import org.junit.Assert; import org.junit.BeforeClass; @@ -15,7 +16,7 @@ import java.util.HashMap; import java.util.Map; -import static io.ably.lib.transport.Defaults.ABLY_AGENT_VERSION; +import static io.ably.pubsub.transport.Defaults.ABLY_AGENT_VERSION; /** * Created by VOstopolets on 8/17/16. @@ -48,7 +49,7 @@ public static void tearDown() { /** * The header Ably-Agent: [lib]/[version] * should be included in all REST requests to the Ably endpoint - * see {@link io.ably.lib.transport.Defaults#ABLY_AGENT_PARAM} + * see {@link io.ably.pubsub.transport.Defaults#ABLY_AGENT_PARAM} *

* Spec: RSC7d, G4, RSA7e2 *

@@ -58,11 +59,10 @@ public void header_lib_channel_publish() { try { /* Init values for local server */ ClientOptions opts = createOptions(testVars.keys[0].keyStr); - opts.environment = null; opts.tls = false; opts.port = server.getListeningPort(); - opts.restHost = "localhost"; - AblyRest ably = new AblyRest(opts); + opts.endpoint = "localhost"; + PubSubHttpClient ably = HttpClientFactory.create(opts); /* Publish message */ String messageName = "test message"; @@ -104,12 +104,11 @@ public void header_client_id_on_channel_publish() { try { /* Init values for local server */ ClientOptions opts = createOptions(testVars.keys[0].keyStr); - opts.environment = null; opts.tls = false; opts.port = server.getListeningPort(); - opts.restHost = "localhost"; + opts.endpoint = "localhost"; opts.clientId = "test client"; - AblyRest ably = new AblyRest(opts); + PubSubHttpClient ably = HttpClientFactory.create(opts); /* Publish message */ String messageName = "test message"; diff --git a/lib/src/test/java/io/ably/lib/test/rest/RestInitTest.java b/lib/src/test/java/io/ably/pubsub/test/http/HttpInitTest.java similarity index 78% rename from lib/src/test/java/io/ably/lib/test/rest/RestInitTest.java rename to lib/src/test/java/io/ably/pubsub/test/http/HttpInitTest.java index ad807b569..34587c5b0 100644 --- a/lib/src/test/java/io/ably/lib/test/rest/RestInitTest.java +++ b/lib/src/test/java/io/ably/pubsub/test/http/HttpInitTest.java @@ -1,4 +1,4 @@ -package io.ably.lib.test.rest; +package io.ably.pubsub.test.http; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -7,21 +7,21 @@ import java.io.ByteArrayOutputStream; import java.io.PrintStream; -import java.util.Locale; -import io.ably.lib.rest.AblyRest; -import io.ably.lib.test.common.Setup; -import io.ably.lib.test.common.Setup.TestVars; -import io.ably.lib.transport.Defaults; -import io.ably.lib.types.AblyException; -import io.ably.lib.types.ClientOptions; -import io.ably.lib.types.ErrorInfo; -import io.ably.lib.util.Log; -import io.ably.lib.util.Log.LogHandler; +import io.ably.pubsub.http.HttpClientFactory; +import io.ably.pubsub.http.PubSubHttpClient; +import io.ably.pubsub.test.common.Setup; +import io.ably.pubsub.test.common.Setup.TestVars; +import io.ably.pubsub.transport.Defaults; +import io.ably.pubsub.types.AblyException; +import io.ably.pubsub.types.ClientOptions; +import io.ably.pubsub.types.ErrorInfo; +import io.ably.pubsub.util.Log; +import io.ably.pubsub.util.Log.LogHandler; import org.junit.Test; -public class RestInitTest { +public class HttpInitTest { /** * Init library with a key only @@ -30,7 +30,7 @@ public class RestInitTest { public void init_key_string() { try { TestVars testVars = Setup.getTestVars(); - new AblyRest(testVars.keys[0].keyStr); + HttpClientFactory.create(new ClientOptions(testVars.keys[0].keyStr)); } catch (AblyException e) { e.printStackTrace(); fail("init0: Unexpected exception instantiating library"); @@ -44,7 +44,7 @@ public void init_key_string() { public void init_null_key_string() { try { String key = null; - new AblyRest(key); + HttpClientFactory.create(new ClientOptions(key)); fail("init_null_key_string: Expected AblyException to be thrown when instantiating library with null key"); } catch (AblyException e) {} } @@ -57,7 +57,7 @@ public void init_key_opts() { try { String sampleKey = "sample:key"; ClientOptions opts = new ClientOptions(sampleKey); - new AblyRest(opts); + HttpClientFactory.create(opts); } catch (AblyException e) { e.printStackTrace(); fail("init_key_opts: Unexpected exception instantiating library"); @@ -71,7 +71,7 @@ public void init_key_opts() { public void init_null_key_opts() { try { ClientOptions opts = new ClientOptions(null); - new AblyRest(opts); + HttpClientFactory.create(opts); fail("init_null_key_opts: Expected AblyException to be thrown when instantiating library with null key in options"); } catch (AblyException e) {} } @@ -84,7 +84,7 @@ public void init_key() { try { TestVars testVars = Setup.getTestVars(); ClientOptions opts = new ClientOptions(testVars.keys[0].keyStr); - new AblyRest(opts); + HttpClientFactory.create(opts); } catch (AblyException e) { e.printStackTrace(); fail("init2: Unexpected exception instantiating library"); @@ -99,7 +99,7 @@ public void init_key() { public void init_no_auth() { try { ClientOptions opts = new ClientOptions(); - new AblyRest(opts); + HttpClientFactory.create(opts); fail("init2: Unexpected success instantiating library"); } catch (AblyException e) { ErrorInfo err = e.errorInfo; @@ -108,7 +108,8 @@ public void init_no_auth() { } /** - * Init library with specified host + * Init library with specified hostname endpoint + * Spec: REC1b2 */ @Test public void init_host() { @@ -117,9 +118,9 @@ public void init_host() { TestVars testVars = Setup.getTestVars(); ClientOptions opts = new ClientOptions(testVars.keys[0].keyStr); - opts.restHost = hostExpected; - AblyRest ably = new AblyRest(opts); - assertEquals("Unexpected host mismatch", hostExpected, ably.options.restHost); + opts.endpoint = hostExpected; + PubSubHttpClient ably = HttpClientFactory.create(opts); + assertEquals("Unexpected host mismatch", hostExpected, ably.httpCore.getPrimaryHost()); } catch (AblyException e) { e.printStackTrace(); fail("init4: Unexpected exception instantiating library"); @@ -137,7 +138,7 @@ public void init_port() { ClientOptions opts = new ClientOptions(testVars.keys[0].keyStr); opts.port = 9998; opts.tlsPort = 9999; - AblyRest ably = new AblyRest(opts); + PubSubHttpClient ably = HttpClientFactory.create(opts); assertEquals("Unexpected port mismatch", Defaults.getPort(opts), opts.tlsPort); } catch (AblyException e) { e.printStackTrace(); @@ -154,7 +155,7 @@ public void init_default_secure() { try { TestVars testVars = Setup.getTestVars(); ClientOptions opts = new ClientOptions(testVars.keys[0].keyStr); - AblyRest ably = new AblyRest(opts); + PubSubHttpClient ably = HttpClientFactory.create(opts); assertEquals("Unexpected port mismatch", Defaults.getPort(opts), Defaults.TLS_PORT); } catch (AblyException e) { e.printStackTrace(); @@ -172,7 +173,7 @@ public void init_insecure() { TestVars testVars = Setup.getTestVars(); ClientOptions opts = new ClientOptions(testVars.keys[0].keyStr); opts.tls = false; - AblyRest ably = new AblyRest(opts); + PubSubHttpClient ably = HttpClientFactory.create(opts); assertEquals("Unexpected scheme mismatch", Defaults.getPort(opts), Defaults.PORT); } catch (AblyException e) { e.printStackTrace(); @@ -214,7 +215,7 @@ public void println(int severity, String tag, String msg, Throwable tr) { } }; opts.logLevel = Log.VERBOSE; - new AblyRest(opts); + HttpClientFactory.create(opts); assertTrue("Log handler not called", init8_logCalled); } catch (AblyException e) { e.printStackTrace(); @@ -239,7 +240,7 @@ public void println(int severity, String tag, String msg, Throwable tr) { } }; opts.logLevel = Log.NONE; - new AblyRest(opts); + HttpClientFactory.create(opts); assertFalse("Log handler incorrectly called", init9_logCalled); } catch (AblyException e) { e.printStackTrace(); @@ -271,17 +272,16 @@ public void init_default_log_output_stream() { } /** - * Init library with 'production' environment - * Spec: RSC11 + * Init library with no endpoint + * Spec: REC1a */ @Test - public void init_production_environment() { + public void init_default_endpoint() { try { TestVars testVars = Setup.getTestVars(); ClientOptions opts = new ClientOptions(testVars.keys[0].keyStr); - opts.environment = "production"; - AblyRest ably = new AblyRest(opts); - assertEquals("Unexpected host mismatch", Defaults.HOST_REST, ably.httpCore.getPrimaryHost()); + PubSubHttpClient ably = HttpClientFactory.create(opts); + assertEquals("Unexpected host mismatch", "main.realtime.ably.net", ably.httpCore.getPrimaryHost()); } catch (AblyException e) { e.printStackTrace(); fail("init4: Unexpected exception instantiating library"); @@ -289,18 +289,17 @@ public void init_production_environment() { } /** - * Init library with given environment - * Spec: RSC11 + * Init library with given routing policy endpoint + * Spec: REC1b4 */ @Test - public void init_given_environment() { - final String givenEnvironment = "staging"; + public void init_given_endpoint() { try { TestVars testVars = Setup.getTestVars(); ClientOptions opts = new ClientOptions(testVars.keys[0].keyStr); - opts.environment = givenEnvironment; - AblyRest ably = new AblyRest(opts); - assertEquals("Unexpected host mismatch", String.format(Locale.ROOT, "%s-%s", givenEnvironment, Defaults.HOST_REST), ably.httpCore.getPrimaryHost()); + opts.endpoint = "acme"; + PubSubHttpClient ably = HttpClientFactory.create(opts); + assertEquals("Unexpected host mismatch", "acme.realtime.ably.net", ably.httpCore.getPrimaryHost()); } catch (AblyException e) { e.printStackTrace(); fail("init4: Unexpected exception instantiating library"); @@ -308,23 +307,20 @@ public void init_given_environment() { } /** - * Init library with given environment and specified host - * Spec: RSC11 + * Init library with given nonprod routing policy endpoint + * Spec: REC1b3 */ @Test - public void init_given_host_environment() { - final String givenEnvironment = "staging"; - final String specifiedHost = "fake.ably.io"; + public void init_given_nonprod_endpoint() { try { TestVars testVars = Setup.getTestVars(); ClientOptions opts = new ClientOptions(testVars.keys[0].keyStr); - opts.restHost = specifiedHost; - opts.environment = givenEnvironment; - AblyRest ably = new AblyRest(opts); - fail("init4: Expected exception instantiating library"); - assertEquals("Unexpected host mismatch", specifiedHost, ably.options.restHost); + opts.endpoint = "nonprod:sandbox"; + PubSubHttpClient ably = HttpClientFactory.create(opts); + assertEquals("Unexpected host mismatch", "sandbox.realtime.ably-nonprod.net", ably.httpCore.getPrimaryHost()); } catch (AblyException e) { - /* pass: Got exception from setting restHost and environment */ + e.printStackTrace(); + fail("init4: Unexpected exception instantiating library"); } } } diff --git a/lib/src/test/java/io/ably/lib/test/rest/RestJWTTest.java b/lib/src/test/java/io/ably/pubsub/test/http/HttpJWTTest.java similarity index 80% rename from lib/src/test/java/io/ably/lib/test/rest/RestJWTTest.java rename to lib/src/test/java/io/ably/pubsub/test/http/HttpJWTTest.java index a998924f7..15f4b89bb 100644 --- a/lib/src/test/java/io/ably/lib/test/rest/RestJWTTest.java +++ b/lib/src/test/java/io/ably/pubsub/test/http/HttpJWTTest.java @@ -1,17 +1,18 @@ -package io.ably.lib.test.rest; +package io.ably.pubsub.test.http; -import io.ably.lib.http.HttpCore; -import io.ably.lib.http.HttpHelpers; -import io.ably.lib.rest.AblyRest; -import io.ably.lib.rest.Auth; -import io.ably.lib.test.common.ParameterizedTest; -import io.ably.lib.test.common.Setup.Key; -import io.ably.lib.types.AblyException; -import io.ably.lib.types.ClientOptions; -import io.ably.lib.types.ErrorInfo; -import io.ably.lib.types.PaginatedResult; -import io.ably.lib.types.Param; -import io.ably.lib.types.Stats; +import io.ably.pubsub.http.HttpCore; +import io.ably.pubsub.http.HttpHelpers; +import io.ably.pubsub.http.HttpClientFactory; +import io.ably.pubsub.http.PubSubHttpClient; +import io.ably.pubsub.http.Auth; +import io.ably.pubsub.test.common.ParameterizedTest; +import io.ably.pubsub.test.common.Setup.Key; +import io.ably.pubsub.types.AblyException; +import io.ably.pubsub.types.ClientOptions; +import io.ably.pubsub.types.ErrorInfo; +import io.ably.pubsub.types.PaginatedResult; +import io.ably.pubsub.types.Param; +import io.ably.pubsub.types.Stats; import org.junit.Test; import java.io.UnsupportedEncodingException; @@ -21,10 +22,10 @@ import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; -public class RestJWTTest extends ParameterizedTest { +public class HttpJWTTest extends ParameterizedTest { private Key key = testVars.keys[0]; - Param[] environment = new Param[]{ new Param("environment", testVars.environment) }; + Param[] environment = new Param[]{ new Param("environment", testVars.endpoint.replace("nonprod:", "")) }; Param[] validKeys = new Param[]{ new Param("keyName", key.keyName), new Param("keySecret", key.keySecret) }; Param[] invalidKeys = new Param[]{ new Param("keyName", key.keyName), new Param("keySecret", "invalidinvalid") }; Param[] tokenEmbedded = new Param[]{ new Param("jwtType", "embedded") }; @@ -39,7 +40,7 @@ public class RestJWTTest extends ParameterizedTest { public void auth_jwt_request() { try { ClientOptions options = buildClientOptions(validKeys); - AblyRest client = new AblyRest(options); + PubSubHttpClient client = HttpClientFactory.create(options); PaginatedResult stats = client.stats(null); assertNotNull("Stats should not be null", stats); } catch (AblyException e) { @@ -55,7 +56,7 @@ public void auth_jwt_request() { public void auth_jwt_request_wrong_keys() { try { ClientOptions options = buildClientOptions(invalidKeys); - AblyRest client = new AblyRest(options); + PubSubHttpClient client = HttpClientFactory.create(options); PaginatedResult stats = client.stats(null); } catch (AblyException e) { assertEquals("Unexpected code from exception", 40144, e.errorInfo.code); @@ -71,7 +72,7 @@ public void auth_jwt_request_wrong_keys() { public void auth_jwt_request_embedded_token() { try { ClientOptions options = buildClientOptions(mergeParams(new Param[][]{environment, validKeys, tokenEmbedded})); - AblyRest client = new AblyRest(options); + PubSubHttpClient client = HttpClientFactory.create(options); PaginatedResult stats = client.stats(null); assertNotNull("Stats should not be null", stats); } catch (AblyException e) { @@ -87,7 +88,7 @@ public void auth_jwt_request_embedded_token() { public void auth_jwt_request_embedded_token_encrypted() { try { ClientOptions options = buildClientOptions(mergeParams(new Param[][]{environment, validKeys, tokenEmbeddedAndEncrypted})); - AblyRest client = new AblyRest(options); + PubSubHttpClient client = HttpClientFactory.create(options); PaginatedResult stats = client.stats(null); assertNotNull("Stats should not be null", stats); } catch (AblyException e) { @@ -105,7 +106,7 @@ public void auth_jwt_request_returntype() { ClientOptions options = createOptions(); options.authUrl = echoServer; options.authParams = mergeParams(new Param[][]{environment, validKeys, jwtReturnType}); - AblyRest client = new AblyRest(options); + PubSubHttpClient client = HttpClientFactory.create(options); PaginatedResult stats = client.stats(null); assertNotNull("Stats should not be null", stats); } catch (AblyException e) { @@ -120,18 +121,18 @@ public void auth_jwt_request_returntype() { @Test public void auth_jwt_request_authcallback() { try { - final AblyRest restJWTRequester = new AblyRest(createOptions(testVars.keys[0].keyStr)); + final PubSubHttpClient httpJWTRequester = HttpClientFactory.create(createOptions(testVars.keys[0].keyStr)); final boolean[] callbackCalled = new boolean[] { false }; Auth.TokenCallback authCallback = new Auth.TokenCallback() { @Override public Object getTokenRequest(Auth.TokenParams params) throws AblyException { callbackCalled[0] = true; - return restJWTRequester.auth.requestToken(params, null); + return httpJWTRequester.auth.requestToken(params, null); } }; ClientOptions optionsWithCallback = createOptions(); optionsWithCallback.authCallback = authCallback; - AblyRest client = new AblyRest(optionsWithCallback); + PubSubHttpClient client = HttpClientFactory.create(optionsWithCallback); PaginatedResult stats = client.stats(null); assertNotNull("Stats should not be null", stats); assertTrue("Callback was not called", callbackCalled[0]); @@ -148,7 +149,7 @@ private ClientOptions buildClientOptions(Param[] params) { try { ClientOptions options = createOptions(); final String[] resultToken = new String[1]; - AblyRest rest = new AblyRest(createOptions(testVars.keys[0].keyStr)); + PubSubHttpClient rest = HttpClientFactory.create(createOptions(testVars.keys[0].keyStr)); HttpHelpers.getUri(rest.httpCore, echoServer, null, params, new HttpCore.ResponseHandler() { @Override public Object handleResponse(HttpCore.Response response, ErrorInfo error) throws AblyException { diff --git a/lib/src/test/java/io/ably/lib/test/rest/RestPresenceTest.java b/lib/src/test/java/io/ably/pubsub/test/http/HttpPresenceTest.java similarity index 95% rename from lib/src/test/java/io/ably/lib/test/rest/RestPresenceTest.java rename to lib/src/test/java/io/ably/pubsub/test/http/HttpPresenceTest.java index 584a53f3c..0ce381952 100644 --- a/lib/src/test/java/io/ably/lib/test/rest/RestPresenceTest.java +++ b/lib/src/test/java/io/ably/pubsub/test/http/HttpPresenceTest.java @@ -1,4 +1,4 @@ -package io.ably.lib.test.rest; +package io.ably.pubsub.test.http; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; @@ -9,16 +9,17 @@ import org.junit.Before; import org.junit.Test; -import io.ably.lib.rest.AblyRest; -import io.ably.lib.rest.Channel; -import io.ably.lib.test.common.ParameterizedTest; -import io.ably.lib.types.AblyException; -import io.ably.lib.types.ClientOptions; -import io.ably.lib.types.PaginatedResult; -import io.ably.lib.types.Param; -import io.ably.lib.types.PresenceMessage; +import io.ably.pubsub.http.HttpClientFactory; +import io.ably.pubsub.http.PubSubHttpClient; +import io.ably.pubsub.http.Channel; +import io.ably.pubsub.test.common.ParameterizedTest; +import io.ably.pubsub.types.AblyException; +import io.ably.pubsub.types.ClientOptions; +import io.ably.pubsub.types.PaginatedResult; +import io.ably.pubsub.types.Param; +import io.ably.pubsub.types.PresenceMessage; -public class RestPresenceTest extends ParameterizedTest { +public class HttpPresenceTest extends ParameterizedTest { private static final String[] clientIds = new String[] { "client_string_0", @@ -27,12 +28,12 @@ public class RestPresenceTest extends ParameterizedTest { "client_string_3" }; - private AblyRest ably_text; + private PubSubHttpClient ably_text; @Before public void setUpBefore() throws Exception { ClientOptions opts_text = createOptions(testVars.keys[0].keyStr); - ably_text = new AblyRest(opts_text); + ably_text = HttpClientFactory.create(opts_text); } /** diff --git a/lib/src/test/java/io/ably/lib/test/rest/RestProxyTest.java b/lib/src/test/java/io/ably/pubsub/test/http/HttpProxyTest.java similarity index 84% rename from lib/src/test/java/io/ably/lib/test/rest/RestProxyTest.java rename to lib/src/test/java/io/ably/pubsub/test/http/HttpProxyTest.java index 94fb26312..e59c91dc6 100644 --- a/lib/src/test/java/io/ably/lib/test/rest/RestProxyTest.java +++ b/lib/src/test/java/io/ably/pubsub/test/http/HttpProxyTest.java @@ -1,4 +1,4 @@ -package io.ably.lib.test.rest; +package io.ably.pubsub.test.http; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; @@ -7,16 +7,17 @@ import org.junit.Ignore; import org.junit.Test; -import io.ably.lib.http.HttpAuth; -import io.ably.lib.rest.AblyRest; -import io.ably.lib.test.common.ParameterizedTest; -import io.ably.lib.types.AblyException; -import io.ably.lib.types.ClientOptions; -import io.ably.lib.types.PaginatedResult; -import io.ably.lib.types.ProxyOptions; -import io.ably.lib.types.Stats; +import io.ably.pubsub.http.HttpAuth; +import io.ably.pubsub.http.HttpClientFactory; +import io.ably.pubsub.http.PubSubHttpClient; +import io.ably.pubsub.test.common.ParameterizedTest; +import io.ably.pubsub.types.AblyException; +import io.ably.pubsub.types.ClientOptions; +import io.ably.pubsub.types.PaginatedResult; +import io.ably.pubsub.types.ProxyOptions; +import io.ably.pubsub.types.Stats; -public class RestProxyTest extends ParameterizedTest { +public class HttpProxyTest extends ParameterizedTest { /** * Check access to stats API via proxy with invalid host, expecting failure @@ -30,7 +31,7 @@ public void proxy_simple_invalid_host() { host = "not-sandbox-proxy.ably.io"; port = 6128; }}; - AblyRest ably = new AblyRest(opts); + PubSubHttpClient ably = HttpClientFactory.create(opts); /* attempt the call, expecting no exception */ ably.stats(null); @@ -55,7 +56,9 @@ public void proxy_simple_invalid_port() { host = "sandbox-proxy.ably.io"; port = 6127; }}; - AblyRest ably = new AblyRest(opts); + /* each attempt waits out the connect timeout, so retrying the fallbacks would outlast the test timeout */ + opts.fallbackHosts = new String[0]; + PubSubHttpClient ably = HttpClientFactory.create(opts); /* attempt the call, expecting no exception */ ably.stats(null); @@ -83,7 +86,7 @@ public void proxy_simple_plain() { host = "sandbox-proxy.ably.io"; port = 6128; }}; - AblyRest ably = new AblyRest(opts); + PubSubHttpClient ably = HttpClientFactory.create(opts); /* attempt the call, expecting no exception */ PaginatedResult stats = ably.stats(null); @@ -108,7 +111,7 @@ public void proxy_simple_tls() { host = "sandbox-proxy.ably.io"; port = 6128; }}; - AblyRest ably = new AblyRest(opts); + PubSubHttpClient ably = HttpClientFactory.create(opts); /* attempt the call, expecting no exception */ PaginatedResult stats = ably.stats(null); @@ -137,7 +140,7 @@ public void proxy_basic_auth_plain() { username = "ably"; password = "password"; }}; - AblyRest ably = new AblyRest(opts); + PubSubHttpClient ably = HttpClientFactory.create(opts); /* attempt the call, expecting no exception */ PaginatedResult stats = ably.stats(null); @@ -166,7 +169,7 @@ public void proxy_digest_auth_plain() { password = "password"; prefAuthType = HttpAuth.Type.DIGEST; }}; - AblyRest ably = new AblyRest(opts); + PubSubHttpClient ably = HttpClientFactory.create(opts); /* attempt the call, expecting no exception */ PaginatedResult stats = ably.stats(null); @@ -192,7 +195,7 @@ public void proxy_basic_auth_tls() { username = "ably"; password = "password"; }}; - AblyRest ably = new AblyRest(opts); + PubSubHttpClient ably = HttpClientFactory.create(opts); /* attempt the call, expecting no exception */ PaginatedResult stats = ably.stats(null); diff --git a/lib/src/test/java/io/ably/lib/test/rest/RestPushTest.java b/lib/src/test/java/io/ably/pubsub/test/http/HttpPushTest.java similarity index 96% rename from lib/src/test/java/io/ably/lib/test/rest/RestPushTest.java rename to lib/src/test/java/io/ably/pubsub/test/http/HttpPushTest.java index d271e75a0..958b9a048 100644 --- a/lib/src/test/java/io/ably/lib/test/rest/RestPushTest.java +++ b/lib/src/test/java/io/ably/pubsub/test/http/HttpPushTest.java @@ -1,23 +1,25 @@ -package io.ably.lib.test.rest; +package io.ably.pubsub.test.http; import com.google.gson.JsonObject; -import io.ably.lib.debug.DebugOptions; -import io.ably.lib.push.PushBase.ChannelSubscription; -import io.ably.lib.realtime.AblyRealtime; -import io.ably.lib.realtime.CompletionListener; -import io.ably.lib.rest.AblyRest; -import io.ably.lib.rest.DeviceDetails; -import io.ably.lib.test.common.Helpers; -import io.ably.lib.test.common.Helpers.CompletionWaiter; -import io.ably.lib.test.common.Helpers.MessageWaiter; -import io.ably.lib.test.common.ParameterizedTest; -import io.ably.lib.test.util.TestCases; -import io.ably.lib.types.AblyException; -import io.ably.lib.types.AsyncPaginatedResult; -import io.ably.lib.types.Callback; -import io.ably.lib.types.PaginatedResult; -import io.ably.lib.types.Param; -import io.ably.lib.util.JsonUtils; +import io.ably.pubsub.debug.DebugOptions; +import io.ably.pubsub.push.PushBase.ChannelSubscription; +import io.ably.pubsub.realtime.PubSubRealtimeClient; +import io.ably.pubsub.realtime.RealtimeClientFactory; +import io.ably.pubsub.realtime.CompletionListener; +import io.ably.pubsub.http.HttpClientFactory; +import io.ably.pubsub.http.PubSubHttpClient; +import io.ably.pubsub.http.DeviceDetails; +import io.ably.pubsub.test.common.Helpers; +import io.ably.pubsub.test.common.Helpers.CompletionWaiter; +import io.ably.pubsub.test.common.Helpers.MessageWaiter; +import io.ably.pubsub.test.common.ParameterizedTest; +import io.ably.pubsub.test.util.TestCases; +import io.ably.pubsub.types.AblyException; +import io.ably.pubsub.types.AsyncPaginatedResult; +import io.ably.pubsub.types.Callback; +import io.ably.pubsub.types.PaginatedResult; +import io.ably.pubsub.types.Param; +import io.ably.pubsub.util.JsonUtils; import org.junit.AfterClass; import org.junit.Before; import org.junit.Ignore; @@ -32,9 +34,9 @@ import static org.junit.Assert.assertEquals; -public class RestPushTest extends ParameterizedTest { - private static AblyRest rest; - private static AblyRealtime realtime; +public class HttpPushTest extends ParameterizedTest { + private static PubSubHttpClient rest; + private static PubSubRealtimeClient realtime; private static DeviceDetails deviceDetails; private static DeviceDetails deviceDetails1ClientA; @@ -78,8 +80,8 @@ public void setUpBefore() throws Exception { httpTracker = new Helpers.RawHttpTracker(); DebugOptions options = createOptions(testVars.keys[0].keyStr); options.httpListener = httpTracker; - rest = new AblyRest(options); - realtime = new AblyRealtime(options); + rest = HttpClientFactory.create(options); + realtime = RealtimeClientFactory.create(options); deviceDetails = DeviceDetails.fromJsonObject(JsonUtils.object() .add("id", "testDeviceDetails") diff --git a/lib/src/test/java/io/ably/lib/test/rest/RestRequestTest.java b/lib/src/test/java/io/ably/pubsub/test/http/HttpRequestTest.java similarity index 94% rename from lib/src/test/java/io/ably/lib/test/rest/RestRequestTest.java rename to lib/src/test/java/io/ably/pubsub/test/http/HttpRequestTest.java index a1791a9bc..ff40e0d34 100644 --- a/lib/src/test/java/io/ably/lib/test/rest/RestRequestTest.java +++ b/lib/src/test/java/io/ably/pubsub/test/http/HttpRequestTest.java @@ -1,4 +1,4 @@ -package io.ably.lib.test.rest; +package io.ably.pubsub.test.http; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -10,7 +10,7 @@ import java.util.Map; import java.util.concurrent.TimeoutException; -import io.ably.lib.transport.Defaults; +import io.ably.pubsub.transport.Defaults; import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -18,28 +18,29 @@ import com.google.gson.JsonElement; -import io.ably.lib.debug.DebugOptions; -import io.ably.lib.http.HttpConstants; -import io.ably.lib.http.HttpUtils; -import io.ably.lib.rest.AblyRest; -import io.ably.lib.rest.Channel; -import io.ably.lib.test.common.Helpers.RawHttpRequest; -import io.ably.lib.test.common.Helpers.RawHttpTracker; -import io.ably.lib.test.common.ParameterizedTest; -import io.ably.lib.types.AblyException; -import io.ably.lib.types.AsyncHttpPaginatedResponse; -import io.ably.lib.types.ClientOptions; -import io.ably.lib.types.ErrorInfo; -import io.ably.lib.types.HttpPaginatedResponse; -import io.ably.lib.types.Message; -import io.ably.lib.types.PaginatedResult; -import io.ably.lib.types.Param; +import io.ably.pubsub.debug.DebugOptions; +import io.ably.pubsub.http.HttpConstants; +import io.ably.pubsub.http.HttpUtils; +import io.ably.pubsub.http.HttpClientFactory; +import io.ably.pubsub.http.PubSubHttpClient; +import io.ably.pubsub.http.Channel; +import io.ably.pubsub.test.common.Helpers.RawHttpRequest; +import io.ably.pubsub.test.common.Helpers.RawHttpTracker; +import io.ably.pubsub.test.common.ParameterizedTest; +import io.ably.pubsub.types.AblyException; +import io.ably.pubsub.types.AsyncHttpPaginatedResponse; +import io.ably.pubsub.types.ClientOptions; +import io.ably.pubsub.types.ErrorInfo; +import io.ably.pubsub.types.HttpPaginatedResponse; +import io.ably.pubsub.types.Message; +import io.ably.pubsub.types.PaginatedResult; +import io.ably.pubsub.types.Param; import net.jodah.concurrentunit.Waiter; /* Spec: RSC19 */ -public class RestRequestTest extends ParameterizedTest { +public class HttpRequestTest extends ParameterizedTest { - private AblyRest setupAbly; + private PubSubHttpClient setupAbly; private String channelName; private String channelAltName; private String channelNamePrefix; @@ -53,7 +54,7 @@ public class RestRequestTest extends ParameterizedTest { @Before public void setUpBefore() throws Exception { ClientOptions opts = createOptions(testVars.keys[0].keyStr); - setupAbly = new AblyRest(opts); + setupAbly = HttpClientFactory.create(opts); channelNamePrefix = "persisted:rest_request_" + testParams.name; channelName = channelNamePrefix + "_channel"; channelAltName = channelNamePrefix + "_alt_channel"; @@ -86,7 +87,7 @@ public void request_simple() { fillInOptions(opts); RawHttpTracker httpListener = new RawHttpTracker(); opts.httpListener = httpListener; - AblyRest ably = new AblyRest(opts); + PubSubHttpClient ably = HttpClientFactory.create(opts); Param[] testParams = new Param[] { new Param("testParam", "testValue") }; Param[] testHeaders = new Param[] { new Param("x-test-header", "testValue") }; @@ -135,7 +136,7 @@ public void request_simple_async() { fillInOptions(opts); final RawHttpTracker httpListener = new RawHttpTracker(); opts.httpListener = httpListener; - AblyRest ably = new AblyRest(opts); + PubSubHttpClient ably = HttpClientFactory.create(opts); ably.requestAsync(HttpConstants.Methods.GET, channelPath, null, null, null, new AsyncHttpPaginatedResponse.Callback() { @Override @@ -194,7 +195,7 @@ public void request_paginated() { try { DebugOptions opts = new DebugOptions(testVars.keys[0].keyStr); fillInOptions(opts); - AblyRest ably = new AblyRest(opts); + PubSubHttpClient ably = HttpClientFactory.create(opts); Param[] params = new Param[] { new Param("prefix", channelNamePrefix) }; Param[] requestHeaders = new Param[] { new Param(Defaults.ABLY_PROTOCOL_VERSION_HEADER, 2) }; @@ -239,7 +240,7 @@ public void request_paginated_async() { try { DebugOptions opts = new DebugOptions(testVars.keys[0].keyStr); fillInOptions(opts); - AblyRest ably = new AblyRest(opts); + PubSubHttpClient ably = HttpClientFactory.create(opts); Param[] params = new Param[] { new Param("prefix", channelNamePrefix) }; Param[] requestHeaders = new Param[] { new Param(Defaults.ABLY_PROTOCOL_VERSION_HEADER, 2) }; @@ -309,7 +310,7 @@ public void request_paginated_limit() { try { DebugOptions opts = new DebugOptions(testVars.keys[0].keyStr); fillInOptions(opts); - AblyRest ably = new AblyRest(opts); + PubSubHttpClient ably = HttpClientFactory.create(opts); Param[] params = new Param[] { new Param("prefix", channelNamePrefix), new Param("limit", "1") }; Param[] requestHeaders = new Param[] { new Param(Defaults.ABLY_PROTOCOL_VERSION_HEADER, 2) }; @@ -373,7 +374,7 @@ public void request_paginated_async_limit() { try { DebugOptions opts = new DebugOptions(testVars.keys[0].keyStr); fillInOptions(opts); - AblyRest ably = new AblyRest(opts); + PubSubHttpClient ably = HttpClientFactory.create(opts); Param[] params = new Param[] { new Param("prefix", channelNamePrefix), new Param("limit", "1") }; Param[] headers = new Param[] { new Param(Defaults.ABLY_PROTOCOL_VERSION_HEADER, 2) }; @@ -482,7 +483,7 @@ public void request_post() { fillInOptions(opts); final RawHttpTracker httpListener = new RawHttpTracker(); opts.httpListener = httpListener; - AblyRest ably = new AblyRest(opts); + PubSubHttpClient ably = HttpClientFactory.create(opts); /* publish a message */ Message message = new Message("Test event", messageData); @@ -535,7 +536,7 @@ public void request_post_async() { fillInOptions(opts); final RawHttpTracker httpListener = new RawHttpTracker(); opts.httpListener = httpListener; - AblyRest ably = new AblyRest(opts); + PubSubHttpClient ably = HttpClientFactory.create(opts); /* publish a message */ Message message = new Message("Test event", messageData); @@ -607,7 +608,7 @@ public void request_404() { try { DebugOptions opts = new DebugOptions(testVars.keys[0].keyStr); fillInOptions(opts); - AblyRest ably = new AblyRest(opts); + PubSubHttpClient ably = HttpClientFactory.create(opts); HttpPaginatedResponse errorResponse = ably.request(HttpConstants.Methods.GET, "/non-existent-path", null, null, null); /* check HttpPaginatedResponse details are present */ @@ -632,7 +633,7 @@ public void request_404_async() { final Waiter waiter = new Waiter(); DebugOptions opts = new DebugOptions(testVars.keys[0].keyStr); fillInOptions(opts); - AblyRest ably = new AblyRest(opts); + PubSubHttpClient ably = HttpClientFactory.create(opts); ably.requestAsync(HttpConstants.Methods.GET, "/non-existent-path", null, null, null, new AsyncHttpPaginatedResponse.Callback() { @Override @@ -676,8 +677,8 @@ public void request_500() { try { DebugOptions opts = new DebugOptions(testVars.keys[0].keyStr); fillInOptions(opts); - opts.environment = "non.existent.env"; - AblyRest ably = new AblyRest(opts); + opts.endpoint = "non.existent.env"; + PubSubHttpClient ably = HttpClientFactory.create(opts); ably.request(HttpConstants.Methods.GET, "/", null, null, null); fail("request_500: Expected an exception"); @@ -697,8 +698,8 @@ public void request_500_async() { final Waiter waiter = new Waiter(); DebugOptions opts = new DebugOptions(testVars.keys[0].keyStr); fillInOptions(opts); - opts.environment = "non.existent.env"; - AblyRest ably = new AblyRest(opts); + opts.endpoint = "non.existent.env"; + PubSubHttpClient ably = HttpClientFactory.create(opts); ably.requestAsync(HttpConstants.Methods.GET, "/", null, null, null, new AsyncHttpPaginatedResponse.Callback() { @Override @@ -735,7 +736,7 @@ public void request_post_with_invalid_connection_key() throws AblyException { DebugOptions opts = new DebugOptions(testVars.keys[0].keyStr); fillInOptions(opts); opts.httpListener = new RawHttpTracker(); - AblyRest ably = new AblyRest(opts); + PubSubHttpClient ably = HttpClientFactory.create(opts); Message message = new Message("Test event", "Test data (invalid key)"); message.connectionKey = "invalid"; HttpUtils.JsonRequestBody requestBody = new HttpUtils.JsonRequestBody(message); diff --git a/lib/src/test/java/io/ably/lib/test/rest/RestSuite.java b/lib/src/test/java/io/ably/pubsub/test/http/HttpSuite.java similarity index 52% rename from lib/src/test/java/io/ably/lib/test/rest/RestSuite.java rename to lib/src/test/java/io/ably/pubsub/test/http/HttpSuite.java index 14a1ba0cc..083d2260b 100644 --- a/lib/src/test/java/io/ably/lib/test/rest/RestSuite.java +++ b/lib/src/test/java/io/ably/pubsub/test/http/HttpSuite.java @@ -1,4 +1,4 @@ -package io.ably.lib.test.rest; +package io.ably.pubsub.test.http; import org.junit.AfterClass; import org.junit.BeforeClass; @@ -9,33 +9,33 @@ import org.junit.runners.Suite; import org.junit.runners.Suite.SuiteClasses; -import io.ably.lib.test.common.Setup; +import io.ably.pubsub.test.common.Setup; @RunWith(Suite.class) @SuiteClasses({ HttpTest.class, HttpHeaderTest.class, - RestRequestTest.class, - RestAppStatsTest.class, - RestInitTest.class, - RestTimeTest.class, - RestAuthTest.class, - RestAuthAttributeTest.class, - RestTokenTest.class, - RestJWTTest.class, - RestCapabilityTest.class, - RestChannelTest.class, - RestChannelHistoryTest.class, - RestChannelPublishTest.class, - RestChannelBulkPublishTest.class, - RestChannelMessageEditTest.class, - RestCryptoTest.class, - RestPresenceTest.class, - RestProxyTest.class, - RestErrorTest.class, - RestPushTest.class + HttpRequestTest.class, + HttpAppStatsTest.class, + HttpInitTest.class, + HttpTimeTest.class, + HttpAuthTest.class, + HttpAuthAttributeTest.class, + HttpTokenTest.class, + HttpJWTTest.class, + HttpCapabilityTest.class, + HttpChannelTest.class, + HttpChannelHistoryTest.class, + HttpChannelPublishTest.class, + HttpChannelBulkPublishTest.class, + HttpChannelMessageEditTest.class, + HttpCryptoTest.class, + HttpPresenceTest.class, + HttpProxyTest.class, + HttpErrorTest.class, + HttpPushTest.class }) -public class RestSuite { +public class HttpSuite { @BeforeClass public static void setUpBeforeClass() throws Exception { @@ -48,7 +48,7 @@ public static void tearDownAfterClass() throws Exception { } public static void main(String[] args) { - Result result = JUnitCore.runClasses(RestSuite.class); + Result result = JUnitCore.runClasses(HttpSuite.class); for(Failure failure : result.getFailures()) { System.out.println(failure.toString()); } diff --git a/lib/src/test/java/io/ably/lib/test/rest/HttpTest.java b/lib/src/test/java/io/ably/pubsub/test/http/HttpTest.java similarity index 93% rename from lib/src/test/java/io/ably/lib/test/rest/HttpTest.java rename to lib/src/test/java/io/ably/pubsub/test/http/HttpTest.java index 0739af550..9a26fc7fb 100644 --- a/lib/src/test/java/io/ably/lib/test/rest/HttpTest.java +++ b/lib/src/test/java/io/ably/pubsub/test/http/HttpTest.java @@ -1,24 +1,24 @@ -package io.ably.lib.test.rest; +package io.ably.pubsub.test.http; import fi.iki.elonen.NanoHTTPD; import fi.iki.elonen.router.RouterNanoHTTPD; -import io.ably.lib.http.AsyncHttpScheduler; -import io.ably.lib.http.Http; -import io.ably.lib.http.HttpConstants; -import io.ably.lib.http.HttpCore; -import io.ably.lib.http.HttpHelpers; -import io.ably.lib.http.SyncHttpScheduler; -import io.ably.lib.rest.AblyRest; -import io.ably.lib.test.util.EmptyPlatformAgentProvider; -import io.ably.lib.test.util.StatusHandler; -import io.ably.lib.test.util.TimeHandler; -import io.ably.lib.transport.Defaults; -import io.ably.lib.types.AblyException; -import io.ably.lib.types.Callback; -import io.ably.lib.types.ClientOptions; -import io.ably.lib.types.ErrorInfo; -import io.ably.lib.types.Param; -import io.ably.lib.util.PlatformAgentProvider; +import io.ably.pubsub.http.AsyncHttpScheduler; +import io.ably.pubsub.http.HttpRequester; +import io.ably.pubsub.http.HttpConstants; +import io.ably.pubsub.http.HttpCore; +import io.ably.pubsub.http.HttpHelpers; +import io.ably.pubsub.http.SyncHttpScheduler; +import io.ably.pubsub.http.HttpClientFactory; +import io.ably.pubsub.http.PubSubHttpClient; +import io.ably.pubsub.test.util.EmptyPlatformAgentProvider; +import io.ably.pubsub.test.util.StatusHandler; +import io.ably.pubsub.test.util.TimeHandler; +import io.ably.pubsub.types.AblyException; +import io.ably.pubsub.types.Callback; +import io.ably.pubsub.types.ClientOptions; +import io.ably.pubsub.types.ErrorInfo; +import io.ably.pubsub.types.Param; +import io.ably.pubsub.util.PlatformAgentProvider; import org.hamcrest.Description; import org.hamcrest.TypeSafeMatcher; import org.junit.AfterClass; @@ -34,8 +34,8 @@ import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; -import io.ably.lib.debug.DebugOptions; -import io.ably.lib.network.HttpRequest; +import io.ably.pubsub.debug.DebugOptions; +import io.ably.pubsub.network.HttpRequest; import java.io.IOException; import java.net.MalformedURLException; @@ -75,7 +75,8 @@ */ public class HttpTest { - private static final String PATTERN_HOST_FALLBACK = "(?i)[a-e]\\.ably-realtime.com"; + private static final String DEFAULT_PRIMARY_HOST = "main.realtime.ably.net"; + private static final String PATTERN_HOST_FALLBACK = "(?i)main\\.[a-e]\\.fallback\\.ably-realtime\\.com"; private static final String CUSTOM_PATTERN_HOST_FALLBACK = "(?i)[f-k]\\.ably-realtime.com"; private static final String[] CUSTOM_HOSTS = { "f.ably-realtime.com", "g.ably-realtime.com", "h.ably-realtime.com", "i.ably-realtime.com", "j.ably-realtime.com", "k.ably-realtime.com" }; private static final String TEST_SERVER_HOST = "localhost"; @@ -161,7 +162,7 @@ public HttpCore setUrlArgumentStack(List urlArgumentStack) { } }.setUrlArgumentStack(urlHostArgumentStack); - Http http = new Http(new AsyncHttpScheduler(httpCore, options), new SyncHttpScheduler(httpCore)); + HttpRequester http = new HttpRequester(new AsyncHttpScheduler(httpCore, options), new SyncHttpScheduler(httpCore)); try { HttpHelpers.ablyHttpExecute( http, "/path/to/fallback", /* Ignore path */ @@ -186,7 +187,7 @@ public HttpCore setUrlArgumentStack(List urlArgumentStack) { */ int expectedCallCount = options.httpMaxRetryCount + 1; assertThat(urlHostArgumentStack.size(), is(equalTo(expectedCallCount))); - assertThat(urlHostArgumentStack.get(0), is(equalTo(Defaults.HOST_REST))); + assertThat(urlHostArgumentStack.get(0), is(equalTo(DEFAULT_PRIMARY_HOST))); for (int i = 1; i < expectedCallCount; i++) { urlHostArgumentStack.get(i).matches(PATTERN_HOST_FALLBACK); @@ -194,7 +195,7 @@ public HttpCore setUrlArgumentStack(List urlArgumentStack) { } /** - * Validates that fallbacks are disabled when ClientOptions#fallbackHosts are set to empty and the only host used is Defaults#HOST_REST + * Validates that fallbacks are disabled when ClientOptions#fallbackHosts are set to empty and the only host used is the default primary host * @throws AblyException */ @@ -222,7 +223,7 @@ public HttpCore setUrlArgumentStack(List urlArgumentStack) { } }.setUrlArgumentStack(urlHostArgumentStack); - Http http = new Http(new AsyncHttpScheduler(httpCore, options), new SyncHttpScheduler(httpCore)); + HttpRequester http = new HttpRequester(new AsyncHttpScheduler(httpCore, options), new SyncHttpScheduler(httpCore)); try { HttpHelpers.ablyHttpExecute( http, "/path/to/fallback", /* Ignore path */ @@ -242,9 +243,9 @@ public HttpCore setUrlArgumentStack(List urlArgumentStack) { assertTrue(false); } - /* Validate that only one host is used and it is Defaults#HOST_REST */ + /* Validate that only one host is used and it is the default primary host */ Assert.assertTrue(urlHostArgumentStack.size() == 1); - assertThat(urlHostArgumentStack.get(0), is(equalTo(Defaults.HOST_REST))); + assertThat(urlHostArgumentStack.get(0), is(equalTo(DEFAULT_PRIMARY_HOST))); } /** @@ -265,7 +266,7 @@ public void http_ably_execute_first_attempt_to_default() throws AblyException { ClientOptions options = new ClientOptions("not:a.key"); options.httpMaxRetryCount = 1; options.fallbackRetryTimeout = 100; - AblyRest ably = new AblyRest(options); + PubSubHttpClient ably = HttpClientFactory.create(options); HttpCore httpCore = Mockito.spy(new HttpCore(ably.options, ably.auth, platformAgentProvider)); @@ -290,7 +291,7 @@ public void http_ably_execute_first_attempt_to_default() throws AblyException { any(HttpCore.ResponseHandler.class) /* Ignore */ ); - Http http = new Http(new AsyncHttpScheduler(httpCore, options), new SyncHttpScheduler(httpCore)); + HttpRequester http = new HttpRequester(new AsyncHttpScheduler(httpCore, options), new SyncHttpScheduler(httpCore)); String responseActual = (String) HttpHelpers.ablyHttpExecute( http, "", /* Ignore */ "", /* Ignore */ @@ -301,7 +302,7 @@ public void http_ably_execute_first_attempt_to_default() throws AblyException { false /* Ignore */ ); - assertThat("Unexpected default primary host", url.getAllValues().get(0).getHost(), is(equalTo(Defaults.HOST_REST))); + assertThat("Unexpected default primary host", url.getAllValues().get(0).getHost(), is(equalTo(DEFAULT_PRIMARY_HOST))); assertThat("Unexpected host fallback", url.getAllValues().get(1).getHost().matches(hostExpectedPattern), is(true)); assertThat("Unexpected response", responseActual, is(equalTo(responseExpected))); @@ -331,7 +332,7 @@ public void http_ably_execute_first_attempt_to_default() throws AblyException { anyBoolean(), /* Ignore */ any(HttpCore.ResponseHandler.class) /* Ignore */ ); - assertThat("Unexpected default primary host", url.getAllValues().get(2).getHost(), is(equalTo(Defaults.HOST_REST))); + assertThat("Unexpected default primary host", url.getAllValues().get(2).getHost(), is(equalTo(DEFAULT_PRIMARY_HOST))); assertThat("Unexpected response", responseActual2, is(equalTo(responseExpected))); } @@ -351,8 +352,8 @@ public void http_ably_execute_first_attempt_to_default() throws AblyException { public void http_ably_execute_overriden_host() throws AblyException { final String fakeHost = "fake.ably.io"; ClientOptions options = new ClientOptions("not:a.key"); - options.restHost = fakeHost; - AblyRest ably = new AblyRest(options); + options.endpoint = fakeHost; + PubSubHttpClient ably = HttpClientFactory.create(options); HttpCore httpCore = Mockito.spy(new HttpCore(ably.options, ably.auth, platformAgentProvider)); @@ -377,7 +378,7 @@ public void http_ably_execute_overriden_host() throws AblyException { any(HttpCore.ResponseHandler.class) /* Ignore */ ); - Http http = new Http(new AsyncHttpScheduler(httpCore, options), new SyncHttpScheduler(httpCore)); + HttpRequester http = new HttpRequester(new AsyncHttpScheduler(httpCore, options), new SyncHttpScheduler(httpCore)); try { HttpHelpers.ablyHttpExecute( http, "", /* Ignore */ @@ -446,7 +447,7 @@ public void http_ably_execute_overriden_host() throws AblyException { public void http_ably_execute_empty_fallback_array() throws AblyException { ClientOptions options = new ClientOptions("not:a.key"); options.fallbackHosts = new String[0]; - AblyRest ably = new AblyRest(options); + PubSubHttpClient ably = HttpClientFactory.create(options); HttpCore httpCore = Mockito.spy(new HttpCore(ably.options, ably.auth, platformAgentProvider)); @@ -471,7 +472,7 @@ public void http_ably_execute_empty_fallback_array() throws AblyException { any(HttpCore.ResponseHandler.class) /* Ignore */ ); - Http http = new Http(new AsyncHttpScheduler(httpCore, options), new SyncHttpScheduler(httpCore)); + HttpRequester http = new HttpRequester(new AsyncHttpScheduler(httpCore, options), new SyncHttpScheduler(httpCore)); try { HttpHelpers.ablyHttpExecute( http, "", /* Ignore */ @@ -499,7 +500,7 @@ public void http_ably_execute_empty_fallback_array() throws AblyException { anyBoolean(), /* Ignore */ any(HttpCore.ResponseHandler.class) /* Ignore */ ); - assertThat("Unexpected host", url.getAllValues().get(0).getHost(), is(equalTo(Defaults.HOST_REST))); + assertThat("Unexpected host", url.getAllValues().get(0).getHost(), is(equalTo(DEFAULT_PRIMARY_HOST))); } /** @@ -522,7 +523,7 @@ public void http_ably_execute_custom_fallback_array() throws AblyException { ClientOptions options = new ClientOptions("not.a:key"); options.fallbackHosts = expectedFallbackHosts; int expectedCallCount = options.httpMaxRetryCount + 1; - AblyRest ably = new AblyRest(options); + PubSubHttpClient ably = HttpClientFactory.create(options); HttpCore httpCore = Mockito.spy(new HttpCore(ably.options, ably.auth, platformAgentProvider)); @@ -547,7 +548,7 @@ public void http_ably_execute_custom_fallback_array() throws AblyException { any(HttpCore.ResponseHandler.class) /* Ignore */ ); - Http http = new Http(new AsyncHttpScheduler(httpCore, options), new SyncHttpScheduler(httpCore)); + HttpRequester http = new HttpRequester(new AsyncHttpScheduler(httpCore, options), new SyncHttpScheduler(httpCore)); String responseActual = (String) HttpHelpers.ablyHttpExecute( http, "", /* Ignore */ "", /* Ignore */ @@ -575,7 +576,7 @@ public void http_ably_execute_custom_fallback_array() throws AblyException { * - other calls executed against a random custom fallback host */ List allValues = url.getAllValues(); assertThat("Unexpected response", responseActual, is(equalTo(responseExpected))); - assertThat("Unexpected default primary host", allValues.get(0).getHost(), is(equalTo(Defaults.HOST_REST))); + assertThat("Unexpected default primary host", allValues.get(0).getHost(), is(equalTo(DEFAULT_PRIMARY_HOST))); for (int i = 1; i < allValues.size(); i++) { assertThat("Unexpected host fallback", fallbackHostsList.contains(allValues.get(i).getHost()), is(true)); } @@ -603,7 +604,7 @@ public void http_ably_execute_custom_fallback() throws AblyException { public T httpExecuteWithRetry(URL url, String method, Param[] headers, RequestBody requestBody, ResponseHandler responseHandler, boolean allowAblyAuth) throws AblyException { urlArgumentStack.add(url.getHost()); /* verify if fallback hosts are from specified list */ - if(!url.getHost().equals(Defaults.HOST_REST)) + if(!url.getHost().equals(DEFAULT_PRIMARY_HOST)) assertTrue(Arrays.asList(CUSTOM_HOSTS).contains(url.getHost())); return super.httpExecuteWithRetry(url, method, headers, requestBody, responseHandler, allowAblyAuth); @@ -615,7 +616,7 @@ public HttpCore setUrlArgumentStack(List urlArgumentStack) { } }.setUrlArgumentStack(urlHostArgumentStack); - Http http = new Http(new AsyncHttpScheduler(httpCore, options), new SyncHttpScheduler(httpCore)); + HttpRequester http = new HttpRequester(new AsyncHttpScheduler(httpCore, options), new SyncHttpScheduler(httpCore)); try { HttpHelpers.ablyHttpExecute( http, "/path/to/fallback", /* Ignore path */ @@ -635,7 +636,7 @@ public HttpCore setUrlArgumentStack(List urlArgumentStack) { int expectedCallCount = options.httpMaxRetryCount + 1; Assert.assertTrue(urlHostArgumentStack.size() == expectedCallCount); - assertThat(urlHostArgumentStack.get(0), is(equalTo(Defaults.HOST_REST))); + assertThat(urlHostArgumentStack.get(0), is(equalTo(DEFAULT_PRIMARY_HOST))); for (int i = 1; i < expectedCallCount; i++) { Assert.assertTrue(urlHostArgumentStack.get(i).matches(CUSTOM_PATTERN_HOST_FALLBACK)); @@ -658,7 +659,7 @@ public void http_execute_nofallback() throws Exception { HttpCore httpCore = Mockito.spy(new HttpCore(new ClientOptions(), null, platformAgentProvider)); String responseExpected = "Lorem Ipsum"; - String hostExpected = Defaults.HOST_REST; + String hostExpected = DEFAULT_PRIMARY_HOST; ArgumentCaptor url = ArgumentCaptor.forClass(URL.class); /* Partially mock httpCore */ @@ -673,7 +674,7 @@ public void http_execute_nofallback() throws Exception { any(HttpCore.ResponseHandler.class) /* Ignore */ ); - Http http = new Http(new AsyncHttpScheduler(httpCore, new ClientOptions()), new SyncHttpScheduler(httpCore)); + HttpRequester http = new HttpRequester(new AsyncHttpScheduler(httpCore, new ClientOptions()), new SyncHttpScheduler(httpCore)); String responseActual = (String) HttpHelpers.ablyHttpExecute( http, "", /* Ignore */ "", /* Ignore */ @@ -741,7 +742,7 @@ public void http_execute_singlefallback() throws Exception { ); /* Call method with real parameters */ - Http http = new Http(new AsyncHttpScheduler(httpCore, new ClientOptions()), new SyncHttpScheduler(httpCore)); + HttpRequester http = new HttpRequester(new AsyncHttpScheduler(httpCore, new ClientOptions()), new SyncHttpScheduler(httpCore)); String responseActual = (String) HttpHelpers.ablyHttpExecute( http, "", /* Ignore */ "", /* Ignore */ @@ -809,7 +810,7 @@ public void http_execute_multiplefallback() throws Exception { any(HttpCore.ResponseHandler.class) /* Ignore */ ); - Http http = new Http(new AsyncHttpScheduler(httpCore, new ClientOptions()), new SyncHttpScheduler(httpCore)); + HttpRequester http = new HttpRequester(new AsyncHttpScheduler(httpCore, new ClientOptions()), new SyncHttpScheduler(httpCore)); String responseActual = (String) HttpHelpers.ablyHttpExecute( http, "", /* Ignore */ "", /* Ignore */ @@ -865,7 +866,7 @@ public void http_execute_fallback_success_timeout_unexpired() throws Exception { opts.fallbackRetryTimeout = 2000L; HttpCore httpCore = Mockito.spy(new HttpCore(opts, null, platformAgentProvider)); - String hostExpected = Defaults.HOST_REST; + String hostExpected = DEFAULT_PRIMARY_HOST; ArgumentCaptor url = ArgumentCaptor.forClass(URL.class); /* Partially mock httpCore */ @@ -886,7 +887,7 @@ public void http_execute_fallback_success_timeout_unexpired() throws Exception { any(HttpCore.ResponseHandler.class) /* Ignore */ ); - Http http = new Http(new AsyncHttpScheduler(httpCore, new ClientOptions()), new SyncHttpScheduler(httpCore)); + HttpRequester http = new HttpRequester(new AsyncHttpScheduler(httpCore, new ClientOptions()), new SyncHttpScheduler(httpCore)); HttpHelpers.ablyHttpExecute( http, "", /* Ignore */ "", /* Ignore */ @@ -950,7 +951,7 @@ public void http_execute_fallback_failure_timeout_unexpired() throws Exception { opts.fallbackRetryTimeout = 2000L; HttpCore httpCore = Mockito.spy(new HttpCore(opts, null, platformAgentProvider)); - String primaryHost = Defaults.HOST_REST; + String primaryHost = DEFAULT_PRIMARY_HOST; ArgumentCaptor url = ArgumentCaptor.forClass(URL.class); /* Partially mock httpCore */ @@ -971,7 +972,7 @@ public void http_execute_fallback_failure_timeout_unexpired() throws Exception { any(HttpCore.ResponseHandler.class) /* Ignore */ ); - Http http = new Http(new AsyncHttpScheduler(httpCore, new ClientOptions()), new SyncHttpScheduler(httpCore)); + HttpRequester http = new HttpRequester(new AsyncHttpScheduler(httpCore, new ClientOptions()), new SyncHttpScheduler(httpCore)); HttpHelpers.ablyHttpExecute( http, "", /* Ignore */ "", /* Ignore */ @@ -1039,7 +1040,7 @@ public void http_execute_fallback_timeout_expired() throws Exception { opts.fallbackRetryTimeout = 2000L; HttpCore httpCore = Mockito.spy(new HttpCore(opts, null, platformAgentProvider)); - String hostExpected = Defaults.HOST_REST; + String hostExpected = DEFAULT_PRIMARY_HOST; ArgumentCaptor url = ArgumentCaptor.forClass(URL.class); /* Partially mock httpCore */ @@ -1060,7 +1061,7 @@ public void http_execute_fallback_timeout_expired() throws Exception { any(HttpCore.ResponseHandler.class) /* Ignore */ ); - Http http = new Http(new AsyncHttpScheduler(httpCore, new ClientOptions()), new SyncHttpScheduler(httpCore)); + HttpRequester http = new HttpRequester(new AsyncHttpScheduler(httpCore, new ClientOptions()), new SyncHttpScheduler(httpCore)); HttpHelpers.ablyHttpExecute( http, "", /* Ignore */ "", /* Ignore */ @@ -1148,7 +1149,7 @@ public void http_execute_excessivefallback() throws AblyException { */ thrown.expect(AblyException.HostFailedException.class); - Http http = new Http(new AsyncHttpScheduler(httpCore, new ClientOptions()), new SyncHttpScheduler(httpCore)); + HttpRequester http = new HttpRequester(new AsyncHttpScheduler(httpCore, new ClientOptions()), new SyncHttpScheduler(httpCore)); HttpHelpers.ablyHttpExecute( http, "", /* Ignore */ "", /* Ignore */ @@ -1280,12 +1281,12 @@ private void test_asynchttp_concurrent(int poolSize, int requestCount, int expec try { ClientOptions options = new ClientOptions("not.a:key"); options.tls = false; - options.restHost = TEST_SERVER_HOST; + options.endpoint = TEST_SERVER_HOST; options.port = TEST_SERVER_PORT; if(poolSize > 0) { options.asyncHttpThreadpoolSize = poolSize; } - final AblyRest ablyRest = new AblyRest(options); + final PubSubHttpClient pubSubHttpClient = HttpClientFactory.create(options); final Object waiter = new Object(); final long startTime = System.currentTimeMillis(); @@ -1294,7 +1295,7 @@ private void test_asynchttp_concurrent(int poolSize, int requestCount, int expec /* start parallel requests */ for(int i = 0; i < requestCount; i++) { - ablyRest.timeAsync(new Callback() { + pubSubHttpClient.timeAsync(new Callback() { @Override public void onSuccess(Long result) { synchronized(waiter) { @@ -1415,7 +1416,7 @@ public void http_fallback_late_success_does_not_repin_expired_timeout() throws E final AtomicInteger requestCount = new AtomicInteger(0); DebugOptions opts = new DebugOptions("appId.keyId:keySecret"); - opts.restHost = primaryHost; + opts.endpoint = primaryHost; opts.fallbackHosts = new String[]{fallbackHost}; opts.fallbackRetryTimeout = 100L; opts.httpMaxRetryCount = 1; @@ -1470,7 +1471,7 @@ public HttpCore.Response onRawHttpRequest(String id, HttpRequest request, String @Override public void onRawHttpException(String id, String method, Throwable t) {} }; - AblyRest client = new AblyRest(opts); + PubSubHttpClient client = HttpClientFactory.create(opts); // req1 (primary→500) + req2 (fallback→200); fallback is now pinned client.time(); diff --git a/lib/src/test/java/io/ably/lib/test/rest/RestTimeTest.java b/lib/src/test/java/io/ably/pubsub/test/http/HttpTimeTest.java similarity index 74% rename from lib/src/test/java/io/ably/lib/test/rest/RestTimeTest.java rename to lib/src/test/java/io/ably/pubsub/test/http/HttpTimeTest.java index bcec86d79..f3000cce5 100644 --- a/lib/src/test/java/io/ably/lib/test/rest/RestTimeTest.java +++ b/lib/src/test/java/io/ably/pubsub/test/http/HttpTimeTest.java @@ -1,4 +1,4 @@ -package io.ably.lib.test.rest; +package io.ably.pubsub.test.http; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; @@ -6,13 +6,14 @@ import org.junit.Test; -import io.ably.lib.rest.AblyRest; -import io.ably.lib.test.common.Helpers.AsyncWaiter; -import io.ably.lib.test.common.ParameterizedTest; -import io.ably.lib.types.AblyException; -import io.ably.lib.types.ClientOptions; +import io.ably.pubsub.http.HttpClientFactory; +import io.ably.pubsub.http.PubSubHttpClient; +import io.ably.pubsub.test.common.Helpers.AsyncWaiter; +import io.ably.pubsub.test.common.ParameterizedTest; +import io.ably.pubsub.types.AblyException; +import io.ably.pubsub.types.ClientOptions; -public class RestTimeTest extends ParameterizedTest { +public class HttpTimeTest extends ParameterizedTest { /** * Verify accuracy of time (to within 60 seconds of actual time) @@ -21,7 +22,7 @@ public class RestTimeTest extends ParameterizedTest { public void time0() { try { ClientOptions opts = createOptions(testVars.keys[0].keyStr); - AblyRest ably = new AblyRest(opts); + PubSubHttpClient ably = HttpClientFactory.create(opts); long reportedTime = ably.time(); long actualTime = System.currentTimeMillis(); assertTrue(Math.abs(actualTime - reportedTime) < 60000); @@ -38,7 +39,7 @@ public void time0() { public void time1() { try { ClientOptions opts = createOptions("not:a.key"); - AblyRest ablyNoAuth = new AblyRest(opts); + PubSubHttpClient ablyNoAuth = HttpClientFactory.create(opts); ablyNoAuth.time(); } catch (AblyException e) { e.printStackTrace(); @@ -47,15 +48,14 @@ public void time1() { } /** - * Verify time fails without valid restHost + * Verify time fails without valid endpoint */ @Test public void time2() { try { ClientOptions opts = createOptions("not:a.key"); - opts.environment = null; - opts.restHost = "this.restHost.does.not.exist"; - AblyRest ably = new AblyRest(opts); + opts.endpoint = "this.endpoint.does.not.exist"; + PubSubHttpClient ably = HttpClientFactory.create(opts); ably.time(); fail("time2: Unexpected success getting time"); } catch (AblyException e) { @@ -70,7 +70,7 @@ public void time2() { public void time_async() { try { ClientOptions opts = createOptions(testVars.keys[0].keyStr); - final AblyRest ably = new AblyRest(opts); + final PubSubHttpClient ably = HttpClientFactory.create(opts); AsyncWaiter callback = new AsyncWaiter(); ably.timeAsync(callback); callback.waitFor(); diff --git a/lib/src/test/java/io/ably/lib/test/rest/RestTokenTest.java b/lib/src/test/java/io/ably/pubsub/test/http/HttpTokenTest.java similarity index 93% rename from lib/src/test/java/io/ably/lib/test/rest/RestTokenTest.java rename to lib/src/test/java/io/ably/pubsub/test/http/HttpTokenTest.java index 2e3921d46..3f8cce4f1 100644 --- a/lib/src/test/java/io/ably/lib/test/rest/RestTokenTest.java +++ b/lib/src/test/java/io/ably/pubsub/test/http/HttpTokenTest.java @@ -1,14 +1,15 @@ -package io.ably.lib.test.rest; - -import io.ably.lib.rest.AblyRest; -import io.ably.lib.rest.Auth.AuthOptions; -import io.ably.lib.rest.Auth.TokenDetails; -import io.ably.lib.rest.Auth.TokenParams; -import io.ably.lib.test.common.ParameterizedTest; -import io.ably.lib.test.common.Setup.Key; -import io.ably.lib.types.AblyException; -import io.ably.lib.types.Capability; -import io.ably.lib.types.ClientOptions; +package io.ably.pubsub.test.http; + +import io.ably.pubsub.http.HttpClientFactory; +import io.ably.pubsub.http.PubSubHttpClient; +import io.ably.pubsub.http.Auth.AuthOptions; +import io.ably.pubsub.http.Auth.TokenDetails; +import io.ably.pubsub.http.Auth.TokenParams; +import io.ably.pubsub.test.common.ParameterizedTest; +import io.ably.pubsub.test.common.Setup.Key; +import io.ably.pubsub.types.AblyException; +import io.ably.pubsub.types.Capability; +import io.ably.pubsub.types.ClientOptions; import org.junit.Before; import org.junit.Test; @@ -17,10 +18,10 @@ import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; -public class RestTokenTest extends ParameterizedTest { +public class HttpTokenTest extends ParameterizedTest { private static String permitAll; - private static AblyRest ably; + private static PubSubHttpClient ably; private static long timeOffset; @Before @@ -29,7 +30,7 @@ public void setUpBefore() throws Exception { capability.addResource("*", "*"); permitAll = capability.toString(); ClientOptions opts = createOptions(testVars.keys[0].keyStr); - ably = new AblyRest(opts); + ably = HttpClientFactory.create(opts); long timeFromService = ably.time(); timeOffset = timeFromService - System.currentTimeMillis(); } diff --git a/lib/src/test/java/io/ably/lib/test/realtime/ConnectionManagerTest.java b/lib/src/test/java/io/ably/pubsub/test/realtime/ConnectionManagerTest.java similarity index 85% rename from lib/src/test/java/io/ably/lib/test/realtime/ConnectionManagerTest.java rename to lib/src/test/java/io/ably/pubsub/test/realtime/ConnectionManagerTest.java index eaaaead97..325ffd373 100644 --- a/lib/src/test/java/io/ably/lib/test/realtime/ConnectionManagerTest.java +++ b/lib/src/test/java/io/ably/pubsub/test/realtime/ConnectionManagerTest.java @@ -1,31 +1,32 @@ -package io.ably.lib.test.realtime; - -import io.ably.lib.debug.DebugOptions; -import io.ably.lib.realtime.AblyRealtime; -import io.ably.lib.realtime.Channel; -import io.ably.lib.realtime.ChannelEvent; -import io.ably.lib.realtime.ChannelState; -import io.ably.lib.realtime.ChannelStateListener; -import io.ably.lib.realtime.Connection; -import io.ably.lib.realtime.ConnectionEvent; -import io.ably.lib.realtime.ConnectionState; -import io.ably.lib.realtime.ConnectionStateListener; -import io.ably.lib.rest.Auth.AuthMethod; -import io.ably.lib.test.common.Helpers; -import io.ably.lib.test.common.Helpers.ChannelWaiter; -import io.ably.lib.test.common.Helpers.ConnectionWaiter; -import io.ably.lib.test.common.ParameterizedTest; -import io.ably.lib.test.util.EmptyPlatformAgentProvider; -import io.ably.lib.test.util.MockWebsocketFactory; -import io.ably.lib.transport.ConnectionManager; -import io.ably.lib.transport.Defaults; -import io.ably.lib.transport.Hosts; -import io.ably.lib.transport.ITransport; -import io.ably.lib.transport.WebSocketTransport; -import io.ably.lib.types.AblyException; -import io.ably.lib.types.ClientOptions; -import io.ably.lib.types.ErrorInfo; -import io.ably.lib.types.ProtocolMessage; +package io.ably.pubsub.test.realtime; + +import io.ably.pubsub.debug.DebugOptions; +import io.ably.pubsub.realtime.PubSubRealtimeClient; +import io.ably.pubsub.realtime.RealtimeClientFactory; +import io.ably.pubsub.realtime.Channel; +import io.ably.pubsub.realtime.ChannelEvent; +import io.ably.pubsub.realtime.ChannelState; +import io.ably.pubsub.realtime.ChannelStateListener; +import io.ably.pubsub.realtime.Connection; +import io.ably.pubsub.realtime.ConnectionEvent; +import io.ably.pubsub.realtime.ConnectionState; +import io.ably.pubsub.realtime.ConnectionStateListener; +import io.ably.pubsub.http.Auth.AuthMethod; +import io.ably.pubsub.test.common.Helpers; +import io.ably.pubsub.test.common.Helpers.ChannelWaiter; +import io.ably.pubsub.test.common.Helpers.ConnectionWaiter; +import io.ably.pubsub.test.common.ParameterizedTest; +import io.ably.pubsub.test.util.EmptyPlatformAgentProvider; +import io.ably.pubsub.test.util.MockWebsocketFactory; +import io.ably.pubsub.transport.ConnectionManager; +import io.ably.pubsub.transport.Defaults; +import io.ably.pubsub.transport.Hosts; +import io.ably.pubsub.transport.ITransport; +import io.ably.pubsub.transport.WebSocketTransport; +import io.ably.pubsub.types.AblyException; +import io.ably.pubsub.types.ClientOptions; +import io.ably.pubsub.types.ErrorInfo; +import io.ably.pubsub.types.ProtocolMessage; import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; @@ -70,7 +71,7 @@ public class ConnectionManagerTest extends ParameterizedTest { @Test public void connectionmanager_fallback_none() throws AblyException { ClientOptions opts = createOptions(testVars.keys[0].keyStr); - try (AblyRealtime ably = new AblyRealtime(opts)) { + try (PubSubRealtimeClient ably = RealtimeClientFactory.create(opts)) { ConnectionManager connectionManager = ably.connection.connectionManager; new Helpers.ConnectionWaiter(ably.connection).waitFor(ConnectionState.connected); @@ -80,7 +81,7 @@ public void connectionmanager_fallback_none() throws AblyException { * - connectionManager is connected to the host without any fallback */ assertThat(connectionManager.getConnectionState().state, is(ConnectionState.connected)); - assertThat(connectionManager.getHost(), is(equalTo(opts.environment + "-realtime.ably.io"))); + assertThat(connectionManager.getHost(), is(equalTo(Defaults.getPrimaryDomain(opts.endpoint)))); } } @@ -98,9 +99,8 @@ public void connectionmanager_fallback_none() throws AblyException { @Test public void connectionmanager_fallback_none_customhost() throws AblyException { ClientOptions opts = createOptions(testVars.keys[0].keyStr); - opts.realtimeHost = "un.reachable.host.example.com"; - opts.environment = null; - try(AblyRealtime ably = new AblyRealtime(opts)) { + opts.endpoint = "un.reachable.host.example.com"; + try(PubSubRealtimeClient ably = RealtimeClientFactory.create(opts)) { ConnectionManager connectionManager = ably.connection.connectionManager; new Helpers.ConnectionWaiter(ably.connection).waitFor(ConnectionState.disconnected); @@ -110,7 +110,7 @@ public void connectionmanager_fallback_none_customhost() throws AblyException { * - connectionManager's last host did not have any fallback */ assertThat(connectionManager.getConnectionState().state, is(ConnectionState.disconnected)); - assertThat(connectionManager.getHost(), is(equalTo(opts.realtimeHost))); + assertThat(connectionManager.getHost(), is(equalTo(opts.endpoint))); } } @@ -130,10 +130,9 @@ public void connectionmanager_fallback_none_customhost() throws AblyException { @Test public void connectionmanager_fallback_none_withoutconnection() throws AblyException { ClientOptions opts = createOptions(testVars.keys[0].keyStr); - opts.realtimeHost = "un.reachable.host"; - opts.environment = null; + opts.endpoint = "un.reachable.host"; opts.autoConnect = false; - try(AblyRealtime ably = new AblyRealtime(opts)) { + try(PubSubRealtimeClient ably = RealtimeClientFactory.create(opts)) { Connection connection = Mockito.mock(Connection.class); final ConnectionManager.Channels channels = Mockito.mock(ConnectionManager.Channels.class); @@ -153,7 +152,7 @@ protected boolean checkConnectivity() { * - connectionManager did not apply any fallback behavior */ assertThat(connectionManager.getConnectionState().state, is(ConnectionState.disconnected)); - assertThat(connectionManager.getHost(), is(equalTo(opts.realtimeHost))); + assertThat(connectionManager.getHost(), is(equalTo(opts.endpoint))); connectionManager.close(); } @@ -162,8 +161,7 @@ protected boolean checkConnectivity() { /** *

* Verifies that fallback behaviour is applied and HTTP client is using same fallback - * endpoint, when the default realtime.ably.io endpoint is being used and has not been - * overriden, and a fallback is applied + * endpoint, when a routing policy endpoint is being used, and a fallback is applied *

*

* Spec: RTN17b, RTN17c @@ -176,12 +174,10 @@ public void connectionmanager_default_fallback_applied() throws AblyException { DebugOptions opts = new DebugOptions(testVars.keys[0].keyStr); fillInOptions(opts); - final Hosts hosts = new Hosts(null, Defaults.HOST_REALTIME, opts); + /* the routing policy endpoint has default fallback hosts */ + final Hosts hosts = new Hosts(opts); final String primaryHost = hosts.getPrimaryHost(); - /* clear the environment override, so we trigger default fallback behaviour */ - opts.environment = null; - /* set up mock transport */ MockWebsocketFactory mockTransport = new MockWebsocketFactory(); opts.transportFactory = mockTransport; @@ -202,7 +198,7 @@ public boolean matches(String hostname) { } }); - try (AblyRealtime ably = new AblyRealtime(opts)) { + try (PubSubRealtimeClient ably = RealtimeClientFactory.create(opts)) { ConnectionManager connectionManager = ably.connection.connectionManager; new Helpers.ConnectionWaiter(ably.connection).waitFor(ConnectionState.connected); @@ -217,7 +213,7 @@ public boolean matches(String hostname) { } /** - * Verify that when environment is overridden, no fallback is used by default + * Verify that when the endpoint is a hostname, no fallback is used by default * *

* Spec: RTN17b @@ -228,7 +224,9 @@ public void connectionmanager_default_endpoint_no_fallback() throws AblyExceptio DebugOptions opts = new DebugOptions(testVars.keys[0].keyStr); fillInOptions(opts); - final Hosts hosts = new Hosts(null, Defaults.HOST_REALTIME, opts); + /* a hostname endpoint has no default fallback hosts (REC2c2) */ + opts.endpoint = Defaults.getPrimaryDomain(opts.endpoint); + final Hosts hosts = new Hosts(opts); final String primaryHost = hosts.getPrimaryHost(); MockWebsocketFactory mockTransport = new MockWebsocketFactory(); @@ -250,7 +248,7 @@ public boolean matches(String hostname) { } }); - try (AblyRealtime ably = new AblyRealtime(opts)) { + try (PubSubRealtimeClient ably = RealtimeClientFactory.create(opts)) { ConnectionManager connectionManager = ably.connection.connectionManager; System.out.println("waiting for disconnected"); @@ -267,7 +265,7 @@ public boolean matches(String hostname) { } /** - * Verify that when environment is overridden and fallback specified, the fallback is used + * Verify that when the endpoint is a hostname and fallback specified, the fallback is used * *

* Spec: RTN17b @@ -278,7 +276,9 @@ public void connectionmanager_default_endpoint_explicit_fallback() throws AblyEx DebugOptions opts = new DebugOptions(testVars.keys[0].keyStr); fillInOptions(opts); - final Hosts hosts = new Hosts(null, Defaults.HOST_REALTIME, opts); + /* a hostname endpoint has no default fallback hosts (REC2c2) */ + opts.endpoint = Defaults.getPrimaryDomain(opts.endpoint); + final Hosts hosts = new Hosts(opts); final String primaryHost = hosts.getPrimaryHost(); opts.fallbackHosts = new String[]{"fallback 1", "fallback 2"}; @@ -302,7 +302,7 @@ public boolean matches(String hostname) { } }); - try (AblyRealtime ably = new AblyRealtime(opts)) { + try (PubSubRealtimeClient ably = RealtimeClientFactory.create(opts)) { ConnectionManager connectionManager = ably.connection.connectionManager; System.out.println("waiting for connected"); @@ -318,57 +318,6 @@ public boolean matches(String hostname) { } } - /** - * Test that default fallback happens with a non-default host if - * fallbackHostsUseDefault is set. - */ - @Ignore("FIXME: fix exception") - @Test - public void connectionmanager_reconnect_default_fallback() throws AblyException { - DebugOptions opts = new DebugOptions(testVars.keys[0].keyStr); - fillInOptions(opts); - - opts.fallbackHostsUseDefault = true; - - final Hosts hosts = new Hosts(null, Defaults.HOST_REALTIME, opts); - final String primaryHost = hosts.getPrimaryHost(); - - MockWebsocketFactory mockTransport = new MockWebsocketFactory(); - opts.transportFactory = mockTransport; - - /* ensure that all connection attempts ultimately resolve to the primary host */ - mockTransport.setHostTransform(new MockWebsocketFactory.HostTransform() { - @Override - public String transformHost(String givenHost) { - return primaryHost; - } - }); - - /* set up a filter on a mock transport to fail connections to the primary host */ - mockTransport.failConnect(new MockWebsocketFactory.HostFilter() { - @Override - public boolean matches(String hostname) { - return hostname.equals(primaryHost); - } - }); - - try (AblyRealtime ably = new AblyRealtime(opts)) { - ConnectionManager connectionManager = ably.connection.connectionManager; - - System.out.println("waiting for connected"); - new Helpers.ConnectionWaiter(ably.connection).waitFor(ConnectionState.connected); - System.out.println("got connected"); - ably.close(); - - /* Verify that, - * - connectionManager is connected - * - connectionManager's last host was a fallback host - */ - assertThat(connectionManager.getConnectionState().state, is(ConnectionState.connected)); - assertThat(connectionManager.getHost(), is(not(equalTo(opts.realtimeHost)))); - } - } - /** * Connect, and then perform a close() from the calling ConnectionManager context; * verify that the closed state is reached, and the connectionmanager thread has exited @@ -376,7 +325,7 @@ public boolean matches(String hostname) { @Test public void close_from_connectionmanager() throws AblyException { ClientOptions opts = createOptions(testVars.keys[0].keyStr); - final AblyRealtime ably = new AblyRealtime(opts); + final PubSubRealtimeClient ably = RealtimeClientFactory.create(opts); final Thread[] threadContainer = new Thread[1]; ably.connection.on(ConnectionEvent.connected, new ConnectionStateListener() { @Override @@ -402,7 +351,7 @@ public void onConnectionStateChanged(ConnectionStateChange state) { @Test public void connectionmanager_close_while_connecting() throws AblyException { ClientOptions opts = createOptions(testVars.keys[0].keyStr); - final AblyRealtime ably = new AblyRealtime(opts); + final PubSubRealtimeClient ably = RealtimeClientFactory.create(opts); ConnectionWaiter connectionWaiter = new ConnectionWaiter(ably.connection); ConnectionManager connectionManager = ably.connection.connectionManager; ably.close(); @@ -412,7 +361,7 @@ public void connectionmanager_close_while_connecting() throws AblyException { assertEquals(1 , connectionWaiter.getCount(ConnectionState.connecting)); assertEquals(0 , connectionWaiter.getCount(ConnectionState.connected)); assertEquals("Verify closed state is reached", ConnectionState.closed, ably.connection.state); - assertThat("fallback hasn't been invoked", connectionManager.getHost(), is(equalTo(opts.environment + "-realtime.ably.io"))); + assertThat("fallback hasn't been invoked", connectionManager.getHost(), is(equalTo(Defaults.getPrimaryDomain(opts.endpoint)))); } /** @@ -423,7 +372,7 @@ public void connectionmanager_close_while_connecting() throws AblyException { @Test public void connectionmanager_restart_race() throws AblyException { ClientOptions opts = createOptions(testVars.keys[0].keyStr); - final AblyRealtime ably = new AblyRealtime(opts); + final PubSubRealtimeClient ably = RealtimeClientFactory.create(opts); ConnectionWaiter connectionWaiter = new ConnectionWaiter(ably.connection); ably.connection.once(ConnectionEvent.connected, new ConnectionStateListener() { @@ -458,7 +407,7 @@ public void onConnectionStateChanged(ConnectionStateChange state) { public void open_from_dedicated_thread() throws AblyException { ClientOptions opts = createOptions(testVars.keys[0].keyStr); opts.autoConnect = false; - final AblyRealtime ably = new AblyRealtime(opts); + final PubSubRealtimeClient ably = RealtimeClientFactory.create(opts); final Thread[] threadContainer = new Thread[1]; ably.connection.on(ConnectionEvent.connected, new ConnectionStateListener() { @Override @@ -505,7 +454,7 @@ public void run() { public void close_from_dedicated_thread() throws AblyException { ClientOptions opts = createOptions(testVars.keys[0].keyStr); opts.autoConnect = false; - final AblyRealtime ably = new AblyRealtime(opts); + final PubSubRealtimeClient ably = RealtimeClientFactory.create(opts); final Thread[] threadContainer = new Thread[1]; ably.connection.on(ConnectionEvent.connected, new ConnectionStateListener() { @Override @@ -548,7 +497,7 @@ public void run() { public void connection_details_has_ttl() throws AblyException { ClientOptions opts = createOptions(testVars.keys[0].keyStr); opts.autoConnect = false; - try (AblyRealtime ably = new AblyRealtime(opts)) { + try (PubSubRealtimeClient ably = RealtimeClientFactory.create(opts)) { Helpers.MutableConnectionManager connectionManager = new Helpers.MutableConnectionManager(ably); // connStateTtl set to default value @@ -574,7 +523,7 @@ public void connection_details_has_ttl() throws AblyException { public void connection_is_closed_after_max_idle_interval() throws AblyException { ClientOptions opts = createOptions(testVars.keys[0].keyStr); opts.realtimeRequestTimeout = 2000; - try(AblyRealtime ably = new AblyRealtime(opts)) { + try(PubSubRealtimeClient ably = RealtimeClientFactory.create(opts)) { // The original max idle interval we receive from the server is 15s. // We should wait for this, plus a tiny bit extra (as we set the new idle interval to be very low @@ -598,7 +547,7 @@ public void connection_is_closed_after_max_idle_interval() throws AblyException public void connection_has_new_id_when_reconnecting_after_statettl_plus_idleinterval_has_passed() throws AblyException { ClientOptions opts = createOptions(testVars.keys[0].keyStr); opts.realtimeRequestTimeout = 2000L; - try(AblyRealtime ably = new AblyRealtime(opts)) { + try(PubSubRealtimeClient ably = RealtimeClientFactory.create(opts)) { /* We want this greater than newTtl + newIdleInterval */ final long waitInDisconnectedState = 3000L; @@ -636,7 +585,7 @@ public void connection_has_new_id_when_reconnecting_after_statettl_plus_idleinte @Test public void connection_has_same_id_when_reconnecting_before_statettl_plus_idleinterval_has_passed() throws AblyException { ClientOptions opts = createOptions(testVars.keys[0].keyStr); - try(AblyRealtime ably = new AblyRealtime(opts)) { + try(PubSubRealtimeClient ably = RealtimeClientFactory.create(opts)) { ConnectionWaiter connectionWaiter = new ConnectionWaiter(ably.connection); connectionWaiter.waitFor(ConnectionState.connected); String firstConnectionId = ably.connection.id; @@ -659,7 +608,7 @@ public void connection_has_same_id_when_reconnecting_before_statettl_plus_idlein @Test public void channels_are_reattached_after_reconnecting_when_statettl_plus_idleinterval_has_passed() throws AblyException { ClientOptions opts = createOptions(testVars.keys[0].keyStr); - try(AblyRealtime ably = new AblyRealtime(opts)) { + try(PubSubRealtimeClient ably = RealtimeClientFactory.create(opts)) { /* We want this greater than newTtl + newIdleInterval */ final long waitInDisconnectedState = 3000L; final ChannelState[] expectedAttachedChannelHistory = new ChannelState[]{ @@ -736,7 +685,7 @@ public void onChannelStateChanged(ChannelStateChange stateChange) { @Test public void connection_manager_enters_disconnected_state_on_transport_failure() throws AblyException, NoSuchFieldException, IllegalAccessException, InterruptedException { ClientOptions opts = createOptions(testVars.keys[0].keyStr); - try(AblyRealtime ably = new AblyRealtime(opts)) { + try(PubSubRealtimeClient ably = RealtimeClientFactory.create(opts)) { ConnectionManager connectionManager = ably.connection.connectionManager; connectionManager.connect(); @@ -772,14 +721,14 @@ public void connection_manager_enters_disconnected_state_on_transport_failure() @Test public void connection_manager_enters_suspended_state_on_transport_failure_after_already_being_disconnected_for_2_minutes() throws AblyException, NoSuchFieldException, IllegalAccessException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException { ClientOptions opts = createOptions(testVars.keys[0].keyStr); - try(AblyRealtime ably = new AblyRealtime(opts)) { + try(PubSubRealtimeClient ably = RealtimeClientFactory.create(opts)) { ConnectionManager connectionManager = ably.connection.connectionManager; connectionManager.connect(); new Helpers.ConnectionManagerWaiter(ably.connection.connectionManager).waitFor(ConnectionState.connected); // Here, we "fake" being disconnected beyond the suspend timer - Class connectionManagerClass = Class.forName("io.ably.lib.transport.ConnectionManager"); - Class disconnectedState = Class.forName("io.ably.lib.transport.ConnectionManager$Disconnected"); + Class connectionManagerClass = Class.forName("io.ably.pubsub.transport.ConnectionManager"); + Class disconnectedState = Class.forName("io.ably.pubsub.transport.ConnectionManager$Disconnected"); Constructor disconnectedStateCtor = disconnectedState.getDeclaredConstructor(connectionManagerClass); disconnectedStateCtor.setAccessible(true); Field connectionStateField = connectionManager.getClass().getDeclaredField("currentState"); @@ -816,7 +765,7 @@ public void connection_manager_sends_close_message_on_closed() throws AblyExcept opts.transportFactory = new ObservedWebsocketTransport.Factory(); // Connect - try(AblyRealtime ably = new AblyRealtime(opts)) { + try(PubSubRealtimeClient ably = RealtimeClientFactory.create(opts)) { ConnectionManager connectionManager = ably.connection.connectionManager; connectionManager.connect(); // Wait for connected status diff --git a/lib/src/test/java/io/ably/lib/test/realtime/RealtimeAnnotationsTest.java b/lib/src/test/java/io/ably/pubsub/test/realtime/RealtimeAnnotationsTest.java similarity index 82% rename from lib/src/test/java/io/ably/lib/test/realtime/RealtimeAnnotationsTest.java rename to lib/src/test/java/io/ably/pubsub/test/realtime/RealtimeAnnotationsTest.java index cfc18bc20..0e4a2ea6d 100644 --- a/lib/src/test/java/io/ably/lib/test/realtime/RealtimeAnnotationsTest.java +++ b/lib/src/test/java/io/ably/pubsub/test/realtime/RealtimeAnnotationsTest.java @@ -1,20 +1,22 @@ -package io.ably.lib.test.realtime; - -import io.ably.lib.realtime.AblyRealtime; -import io.ably.lib.realtime.Channel; -import io.ably.lib.realtime.ChannelState; -import io.ably.lib.rest.AblyRest; -import io.ably.lib.test.common.Helpers; -import io.ably.lib.test.common.ParameterizedTest; -import io.ably.lib.types.AblyException; -import io.ably.lib.types.Annotation; -import io.ably.lib.types.AnnotationAction; -import io.ably.lib.types.ChannelMode; -import io.ably.lib.types.ChannelOptions; -import io.ably.lib.types.ClientOptions; -import io.ably.lib.types.Message; -import io.ably.lib.types.Param; -import io.ably.lib.types.PaginatedResult; +package io.ably.pubsub.test.realtime; + +import io.ably.pubsub.realtime.PubSubRealtimeClient; +import io.ably.pubsub.realtime.RealtimeClientFactory; +import io.ably.pubsub.realtime.Channel; +import io.ably.pubsub.realtime.ChannelState; +import io.ably.pubsub.http.HttpClientFactory; +import io.ably.pubsub.http.PubSubHttpClient; +import io.ably.pubsub.test.common.Helpers; +import io.ably.pubsub.test.common.ParameterizedTest; +import io.ably.pubsub.types.AblyException; +import io.ably.pubsub.types.Annotation; +import io.ably.pubsub.types.AnnotationAction; +import io.ably.pubsub.types.ChannelMode; +import io.ably.pubsub.types.ChannelOptions; +import io.ably.pubsub.types.ClientOptions; +import io.ably.pubsub.types.Message; +import io.ably.pubsub.types.Param; +import io.ably.pubsub.types.PaginatedResult; import org.junit.Rule; import org.junit.Test; import org.junit.rules.Timeout; @@ -75,11 +77,11 @@ public void publish_and_subscribe_annotations() throws Exception { Annotation emoji2Annotation = new Annotation(); emoji2Annotation.type = "reaction:distinct.v1"; emoji2Annotation.name = "😕"; - testChannel.restChannel.annotations.publish(receivedMessage[0].serial, emoji2Annotation); + testChannel.httpChannel.annotations.publish(receivedMessage[0].serial, emoji2Annotation); waiter.waitFor(); - assertNotNull("Rest annotation should be received", receivedAnnotation[0]); + assertNotNull("HTTP-published annotation should be received", receivedAnnotation[0]); assertEquals(AnnotationAction.ANNOTATION_CREATE, receivedAnnotation[0].action); assertEquals(receivedMessage[0].serial, receivedAnnotation[0].messageSerial); assertEquals("reaction:distinct.v1", receivedAnnotation[0].type); @@ -111,7 +113,7 @@ public void get_all_annotations() throws Exception { Annotation annotation = new Annotation(); annotation.type = "reaction:distinct.v1"; annotation.name = emoji; - testChannel.restChannel.annotations.publish(receivedMessage[0].serial, annotation); + testChannel.httpChannel.annotations.publish(receivedMessage[0].serial, annotation); } waiter.waitFor(6); @@ -157,9 +159,9 @@ private class TestChannel { TestChannel(String channelName) throws AblyException { ClientOptions opts = createOptions(testVars.keys[0].keyStr); opts.clientId = UUID.randomUUID().toString(); - rest = new AblyRest(opts); - restChannel = rest.channels.get(channelName); - realtime = new AblyRealtime(opts); + rest = HttpClientFactory.create(opts); + httpChannel = rest.channels.get(channelName); + realtime = RealtimeClientFactory.create(opts); ChannelOptions channelOptions = new ChannelOptions(); channelOptions.modes = new ChannelMode[] { ChannelMode.publish, ChannelMode.subscribe, ChannelMode.annotation_publish, ChannelMode.annotation_subscribe @@ -175,10 +177,10 @@ void dispose() throws Exception { rest.close(); } - AblyRest rest; - AblyRealtime realtime; - io.ably.lib.rest.Channel restChannel; - io.ably.lib.realtime.Channel realtimeChannel; + PubSubHttpClient rest; + PubSubRealtimeClient realtime; + io.ably.pubsub.http.Channel httpChannel; + io.ably.pubsub.realtime.Channel realtimeChannel; } } diff --git a/lib/src/test/java/io/ably/lib/test/realtime/RealtimeAuthTest.java b/lib/src/test/java/io/ably/pubsub/test/realtime/RealtimeAuthTest.java similarity index 83% rename from lib/src/test/java/io/ably/lib/test/realtime/RealtimeAuthTest.java rename to lib/src/test/java/io/ably/pubsub/test/realtime/RealtimeAuthTest.java index d46014e58..b738da5f2 100644 --- a/lib/src/test/java/io/ably/lib/test/realtime/RealtimeAuthTest.java +++ b/lib/src/test/java/io/ably/pubsub/test/realtime/RealtimeAuthTest.java @@ -1,27 +1,29 @@ -package io.ably.lib.test.realtime; - -import io.ably.lib.debug.DebugOptions; -import io.ably.lib.realtime.AblyRealtime; -import io.ably.lib.realtime.Channel; -import io.ably.lib.realtime.ChannelState; -import io.ably.lib.realtime.ConnectionState; -import io.ably.lib.realtime.ConnectionStateListener; -import io.ably.lib.rest.AblyRest; -import io.ably.lib.rest.Auth; -import io.ably.lib.rest.Auth.TokenDetails; -import io.ably.lib.test.common.Helpers; -import io.ably.lib.test.common.Helpers.ChannelWaiter; -import io.ably.lib.test.common.Helpers.CompletionSet; -import io.ably.lib.test.common.Helpers.ConnectionWaiter; -import io.ably.lib.test.common.ParameterizedTest; -import io.ably.lib.test.common.Setup; -import io.ably.lib.types.AblyException; -import io.ably.lib.types.ClientOptions; -import io.ably.lib.types.ErrorInfo; -import io.ably.lib.types.Message; -import io.ably.lib.types.NonRetriableTokenException; -import io.ably.lib.types.Param; -import io.ably.lib.types.ProtocolMessage; +package io.ably.pubsub.test.realtime; + +import io.ably.pubsub.debug.DebugOptions; +import io.ably.pubsub.realtime.PubSubRealtimeClient; +import io.ably.pubsub.realtime.RealtimeClientFactory; +import io.ably.pubsub.realtime.Channel; +import io.ably.pubsub.realtime.ChannelState; +import io.ably.pubsub.realtime.ConnectionState; +import io.ably.pubsub.realtime.ConnectionStateListener; +import io.ably.pubsub.http.HttpClientFactory; +import io.ably.pubsub.http.PubSubHttpClient; +import io.ably.pubsub.http.Auth; +import io.ably.pubsub.http.Auth.TokenDetails; +import io.ably.pubsub.test.common.Helpers; +import io.ably.pubsub.test.common.Helpers.ChannelWaiter; +import io.ably.pubsub.test.common.Helpers.CompletionSet; +import io.ably.pubsub.test.common.Helpers.ConnectionWaiter; +import io.ably.pubsub.test.common.ParameterizedTest; +import io.ably.pubsub.test.common.Setup; +import io.ably.pubsub.types.AblyException; +import io.ably.pubsub.types.ClientOptions; +import io.ably.pubsub.types.ErrorInfo; +import io.ably.pubsub.types.Message; +import io.ably.pubsub.types.NonRetriableTokenException; +import io.ably.pubsub.types.Param; +import io.ably.pubsub.types.ProtocolMessage; import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; @@ -44,13 +46,14 @@ public class RealtimeAuthTest extends ParameterizedTest { public Timeout testTimeout = Timeout.seconds(30); /** - * Verifies an Exception is thrown, when client is initialized with an empty key + * Verifies an Exception is thrown, when a client is initialized with an empty key + * (the options reject it before the client is built) * * @throws IllegalArgumentException */ @Test(expected = IllegalArgumentException.class) public void auth_client_cannot_be_initialized_with_empty_key() throws AblyException { - new AblyRealtime(""); + RealtimeClientFactory.create(new ClientOptions("")); } /** @@ -67,7 +70,7 @@ public void auth_client_match_tokendetails_null_clientId() { try { /* init ably for token */ ClientOptions optsForToken = createOptions(testVars.keys[0].keyStr); - final AblyRest ablyForToken = new AblyRest(optsForToken); + final PubSubHttpClient ablyForToken = HttpClientFactory.create(optsForToken); /* get token */ Auth.TokenParams tokenParams = new Auth.TokenParams(); @@ -79,18 +82,18 @@ public void auth_client_match_tokendetails_null_clientId() { ClientOptions opts = createOptions(); opts.clientId = null; opts.tokenDetails = tokenDetails; - AblyRealtime ablyRealtime = new AblyRealtime(opts); + PubSubRealtimeClient realtimeClient = RealtimeClientFactory.create(opts); System.out.println("done create ably"); /* wait for connected state */ - Helpers.ConnectionWaiter connectionWaiter = new Helpers.ConnectionWaiter(ablyRealtime.connection); + Helpers.ConnectionWaiter connectionWaiter = new Helpers.ConnectionWaiter(realtimeClient.connection); connectionWaiter.waitFor(ConnectionState.connected); - assertEquals("Verify connected state is reached", ConnectionState.connected, ablyRealtime.connection.state); + assertEquals("Verify connected state is reached", ConnectionState.connected, realtimeClient.connection.state); /* check expected clientId */ - assertNull("Auth#clientId is expected to be null", ablyRealtime.auth.clientId); + assertNull("Auth#clientId is expected to be null", realtimeClient.auth.clientId); - ablyRealtime.close(); + realtimeClient.close(); } catch (AblyException e) { e.printStackTrace(); fail(); @@ -105,7 +108,7 @@ public void realtime_connection_with_auth_url_in_query_string_connects() { try { /* init ably for token */ ClientOptions optsForToken = createOptions(testVars.keys[0].keyStr); - final AblyRest ablyForToken = new AblyRest(optsForToken); + final PubSubHttpClient ablyForToken = HttpClientFactory.create(optsForToken); /* get token */ Auth.TokenParams tokenParams = new Auth.TokenParams(); @@ -116,15 +119,15 @@ public void realtime_connection_with_auth_url_in_query_string_connects() { ClientOptions opts = createOptions(); opts.authUrl = "https://echo.ably.io/?body="+ URLEncoder.encode(tokenDetails.token); opts.useTokenAuth = true; - AblyRealtime ablyRealtime = new AblyRealtime(opts); + PubSubRealtimeClient realtimeClient = RealtimeClientFactory.create(opts); System.out.println("done create ably"); /* wait for connected state */ - Helpers.ConnectionWaiter connectionWaiter = new Helpers.ConnectionWaiter(ablyRealtime.connection); + Helpers.ConnectionWaiter connectionWaiter = new Helpers.ConnectionWaiter(realtimeClient.connection); connectionWaiter.waitFor(ConnectionState.connected); - assertEquals("Verify connected state is reached", ConnectionState.connected, ablyRealtime.connection.state); + assertEquals("Verify connected state is reached", ConnectionState.connected, realtimeClient.connection.state); - ablyRealtime.close(); + realtimeClient.close(); } catch (AblyException e) { e.printStackTrace(); fail(); @@ -147,11 +150,11 @@ public void realtime_connection_with_auth_url_in_query_string_connects() { */ @Test public void auth_client_fails() { - AblyRealtime ablyRealtime = null; + PubSubRealtimeClient realtimeClient = null; try { /* init ably for token */ ClientOptions optsForToken = createOptions(testVars.keys[0].keyStr); - AblyRest ablyForToken = new AblyRest(optsForToken); + PubSubHttpClient ablyForToken = HttpClientFactory.create(optsForToken); /* get token */ TokenDetails tokenDetails = ablyForToken.auth.requestToken(null, null); @@ -163,17 +166,17 @@ public void auth_client_fails() { opts.authUrl = "https://echo.ably.io/respondwith"; opts.authParams = new Param[]{ new Param("status", 403)}; - ablyRealtime = new AblyRealtime(opts); - ablyRealtime.connection.connect(); + realtimeClient = RealtimeClientFactory.create(opts); + realtimeClient.connection.connect(); /* wait for connected state */ - Helpers.ConnectionWaiter connectionWaiter = new Helpers.ConnectionWaiter(ablyRealtime.connection); + Helpers.ConnectionWaiter connectionWaiter = new Helpers.ConnectionWaiter(realtimeClient.connection); connectionWaiter.waitFor(ConnectionState.connected); try { opts.tokenDetails = null; /* try to authorize */ - ablyRealtime.auth.authorize(null, opts); + realtimeClient.auth.authorize(null, opts); } catch (AblyException e) { /* check expected error codes */ assertEquals(403, e.errorInfo.statusCode); @@ -187,16 +190,16 @@ public void auth_client_fails() { assertEquals(80019, lastStateChange.reason.code); assertEquals(403, lastStateChange.reason.statusCode); - assertEquals("Verify connected state has failed", ConnectionState.failed, ablyRealtime.connection.state); - assertEquals("Check correct cause error code", 403, ablyRealtime.connection.reason.statusCode); - assertEquals(80019, ablyRealtime.connection.reason.code); + assertEquals("Verify connected state has failed", ConnectionState.failed, realtimeClient.connection.state); + assertEquals("Check correct cause error code", 403, realtimeClient.connection.reason.statusCode); + assertEquals(80019, realtimeClient.connection.reason.code); } catch (AblyException e) { e.printStackTrace(); fail(); } finally { - assert ablyRealtime != null; - ablyRealtime.close(); + assert realtimeClient != null; + realtimeClient.close(); } } @@ -213,11 +216,11 @@ class NonRetriableRuntimeException extends RuntimeException implements NonRetria } Exception exception = new NonRetriableRuntimeException(); - final AblyRealtime ablyRealtime = createAblyRealtimeWithTokenAuthError(exception); + final PubSubRealtimeClient realtimeClient = createAblyRealtimeWithTokenAuthError(exception); - ablyRealtime.connection.connect(); + realtimeClient.connection.connect(); - waitAndAssertConnectionState(ablyRealtime, ConnectionState.failed, 403, 80019); + waitAndAssertConnectionState(realtimeClient, ConnectionState.failed, 403, 80019); } catch (AblyException e) { e.printStackTrace(); fail(); @@ -231,11 +234,11 @@ class NonRetriableRuntimeException extends RuntimeException implements NonRetria public void auth_client_fails_when_auth_token_fails_with_ably_exception_with_status_code_403() { try { Exception exception = AblyException.fromErrorInfo(new ErrorInfo("A non retriable Ably exception", 403, 80040)); - final AblyRealtime ablyRealtime = createAblyRealtimeWithTokenAuthError(exception); + final PubSubRealtimeClient realtimeClient = createAblyRealtimeWithTokenAuthError(exception); - ablyRealtime.connection.connect(); + realtimeClient.connection.connect(); - waitAndAssertConnectionState(ablyRealtime, ConnectionState.failed, 403, 80019); + waitAndAssertConnectionState(realtimeClient, ConnectionState.failed, 403, 80019); } catch (AblyException e) { e.printStackTrace(); fail(); @@ -249,11 +252,11 @@ public void auth_client_fails_when_auth_token_fails_with_ably_exception_with_sta public void auth_client_does_not_fail_when_auth_token_fails_with_an_ably_exception() { try { Exception exception = AblyException.fromErrorInfo(new ErrorInfo("An Ably exception", 401, 80040)); - final AblyRealtime ablyRealtime = createAblyRealtimeWithTokenAuthError(exception); + final PubSubRealtimeClient realtimeClient = createAblyRealtimeWithTokenAuthError(exception); - ablyRealtime.connection.connect(); + realtimeClient.connection.connect(); - waitAndAssertConnectionState(ablyRealtime, ConnectionState.disconnected, 401, 80019); + waitAndAssertConnectionState(realtimeClient, ConnectionState.disconnected, 401, 80019); } catch (AblyException e) { e.printStackTrace(); fail(); @@ -267,11 +270,11 @@ public void auth_client_does_not_fail_when_auth_token_fails_with_an_ably_excepti public void auth_client_does_not_fail_when_auth_token_fails_with_a_runtime_exception() { try { Exception exception = new RuntimeException("A runtime exception"); - final AblyRealtime ablyRealtime = createAblyRealtimeWithTokenAuthError(exception); + final PubSubRealtimeClient realtimeClient = createAblyRealtimeWithTokenAuthError(exception); - ablyRealtime.connection.connect(); + realtimeClient.connection.connect(); - waitAndAssertConnectionState(ablyRealtime, ConnectionState.disconnected, 401, 80019); + waitAndAssertConnectionState(realtimeClient, ConnectionState.disconnected, 401, 80019); } catch (AblyException e) { e.printStackTrace(); fail(); @@ -282,19 +285,19 @@ public void auth_client_does_not_fail_when_auth_token_fails_with_a_runtime_excep * Waits for the Ably connection to enter the [connectionState] and once it happens asserts that the connection state, * status code and code have expected values. */ - private void waitAndAssertConnectionState(AblyRealtime ablyRealtime,ConnectionState connectionState, int statusCode, int code){ - Helpers.ConnectionWaiter connectionWaiter = new Helpers.ConnectionWaiter(ablyRealtime.connection); + private void waitAndAssertConnectionState(PubSubRealtimeClient realtimeClient,ConnectionState connectionState, int statusCode, int code){ + Helpers.ConnectionWaiter connectionWaiter = new Helpers.ConnectionWaiter(realtimeClient.connection); connectionWaiter.waitFor(connectionState); - assertEquals("Verify connected state has changed", connectionState, ablyRealtime.connection.state); - assertEquals("Check correct cause error status code", statusCode, ablyRealtime.connection.reason.statusCode); - assertEquals("Check correct cause error code", code, ablyRealtime.connection.reason.code); + assertEquals("Verify connected state has changed", connectionState, realtimeClient.connection.state); + assertEquals("Check correct cause error status code", statusCode, realtimeClient.connection.reason.statusCode); + assertEquals("Check correct cause error code", code, realtimeClient.connection.reason.code); } /** * Create ably realtime with auth callback which throws the specified exception. */ - private AblyRealtime createAblyRealtimeWithTokenAuthError(final Exception exception) throws AblyException { + private PubSubRealtimeClient createAblyRealtimeWithTokenAuthError(final Exception exception) throws AblyException { ClientOptions opts = createOptions(testVars.keys[0].keyStr); opts.autoConnect = false; opts.useTokenAuth = true; @@ -310,7 +313,7 @@ public Object getTokenRequest(Auth.TokenParams params) throws AblyException { } } }; - return new AblyRealtime(opts); + return RealtimeClientFactory.create(opts); } /** @@ -327,7 +330,7 @@ public void auth_client_match_token_null_clientId() { try { /* init ably for token */ ClientOptions optsForToken = createOptions(testVars.keys[0].keyStr); - final AblyRest ablyForToken = new AblyRest(optsForToken); + final PubSubHttpClient ablyForToken = HttpClientFactory.create(optsForToken); /* get token */ Auth.TokenParams tokenParams = new Auth.TokenParams(); @@ -339,18 +342,18 @@ public void auth_client_match_token_null_clientId() { ClientOptions opts = createOptions(); opts.clientId = null; opts.token = tokenDetails.token; - AblyRealtime ablyRealtime = new AblyRealtime(opts); + PubSubRealtimeClient realtimeClient = RealtimeClientFactory.create(opts); System.out.println("done create ably"); /* wait for connected state */ - Helpers.ConnectionWaiter connectionWaiter = new Helpers.ConnectionWaiter(ablyRealtime.connection); + Helpers.ConnectionWaiter connectionWaiter = new Helpers.ConnectionWaiter(realtimeClient.connection); connectionWaiter.waitFor(ConnectionState.connected); - assertEquals("Verify connected state is reached", ConnectionState.connected, ablyRealtime.connection.state); + assertEquals("Verify connected state is reached", ConnectionState.connected, realtimeClient.connection.state); /* check expected clientId */ - assertNull("Auth#clientId is expected to be null", ablyRealtime.auth.clientId); + assertNull("Auth#clientId is expected to be null", realtimeClient.auth.clientId); - ablyRealtime.close(); + realtimeClient.close(); } catch (AblyException e) { e.printStackTrace(); fail(); @@ -370,7 +373,7 @@ public void auth_clientid_null_before_auth() { /* create token with clientId */ ClientOptions optsForToken = createOptions(testVars.keys[0].keyStr); optsForToken.clientId = clientId; - AblyRest ablyForToken = new AblyRest(optsForToken); + PubSubHttpClient ablyForToken = HttpClientFactory.create(optsForToken); TokenDetails tokenDetails = ablyForToken.auth.requestToken(null, null); /* create ably realtime */ @@ -378,21 +381,21 @@ public void auth_clientid_null_before_auth() { opts.clientId = null; opts.token = tokenDetails.token; opts.autoConnect = false; - AblyRealtime ablyRealtime = new AblyRealtime(opts); + PubSubRealtimeClient realtimeClient = RealtimeClientFactory.create(opts); /* check expected clientId */ - assertNull("Auth#clientId is expected to be null", ablyRealtime.auth.clientId); + assertNull("Auth#clientId is expected to be null", realtimeClient.auth.clientId); /* wait for connected state */ - ablyRealtime.connection.connect(); - Helpers.ConnectionWaiter connectionWaiter = new Helpers.ConnectionWaiter(ablyRealtime.connection); + realtimeClient.connection.connect(); + Helpers.ConnectionWaiter connectionWaiter = new Helpers.ConnectionWaiter(realtimeClient.connection); connectionWaiter.waitFor(ConnectionState.connected); - assertEquals("Verify connected state is reached", ConnectionState.connected, ablyRealtime.connection.state); + assertEquals("Verify connected state is reached", ConnectionState.connected, realtimeClient.connection.state); /* check expected clientId */ - assertEquals("Auth#clientId is expected to be set", clientId, ablyRealtime.auth.clientId); + assertEquals("Auth#clientId is expected to be set", clientId, realtimeClient.auth.clientId); - ablyRealtime.close(); + realtimeClient.close(); } catch (AblyException e) { e.printStackTrace(); fail(); @@ -415,7 +418,7 @@ public void auth_client_match_tokendetails_wildcard_clientId() { try { /* init ably for token */ ClientOptions optsForToken = createOptions(testVars.keys[0].keyStr); - final AblyRest ablyForToken = new AblyRest(optsForToken); + final PubSubHttpClient ablyForToken = HttpClientFactory.create(optsForToken); /* get token */ Auth.TokenParams tokenParams = new Auth.TokenParams(); @@ -427,18 +430,18 @@ public void auth_client_match_tokendetails_wildcard_clientId() { ClientOptions opts = createOptions(); opts.clientId = "options clientId"; opts.tokenDetails = tokenDetails; - AblyRealtime ablyRealtime = new AblyRealtime(opts); + PubSubRealtimeClient realtimeClient = RealtimeClientFactory.create(opts); System.out.println("done create ably"); /* wait for connected state */ - Helpers.ConnectionWaiter connectionWaiter = new Helpers.ConnectionWaiter(ablyRealtime.connection); + Helpers.ConnectionWaiter connectionWaiter = new Helpers.ConnectionWaiter(realtimeClient.connection); connectionWaiter.waitFor(ConnectionState.connected); - assertEquals("Verify connected state is reached", ConnectionState.connected, ablyRealtime.connection.state); + assertEquals("Verify connected state is reached", ConnectionState.connected, realtimeClient.connection.state); /* check expected clientId */ - assertEquals("Auth#clientId is expected to be set", "options clientId", ablyRealtime.auth.clientId); + assertEquals("Auth#clientId is expected to be set", "options clientId", realtimeClient.auth.clientId); - ablyRealtime.close(); + realtimeClient.close(); } catch (AblyException e) { e.printStackTrace(); fail(); @@ -461,7 +464,7 @@ public void auth_client_match_token_wildcard_clientId() { try { /* init ably for token */ ClientOptions optsForToken = createOptions(testVars.keys[0].keyStr); - final AblyRest ablyForToken = new AblyRest(optsForToken); + final PubSubHttpClient ablyForToken = HttpClientFactory.create(optsForToken); /* get token */ Auth.TokenParams tokenParams = new Auth.TokenParams(); @@ -473,18 +476,18 @@ public void auth_client_match_token_wildcard_clientId() { ClientOptions opts = createOptions(); opts.clientId = "options clientId"; opts.token = tokenDetails.token; - AblyRealtime ablyRealtime = new AblyRealtime(opts); + PubSubRealtimeClient realtimeClient = RealtimeClientFactory.create(opts); System.out.println("done create ably"); /* wait for connected state */ - Helpers.ConnectionWaiter connectionWaiter = new Helpers.ConnectionWaiter(ablyRealtime.connection); + Helpers.ConnectionWaiter connectionWaiter = new Helpers.ConnectionWaiter(realtimeClient.connection); connectionWaiter.waitFor(ConnectionState.connected); - assertEquals("Verify connected state is reached", ConnectionState.connected, ablyRealtime.connection.state); + assertEquals("Verify connected state is reached", ConnectionState.connected, realtimeClient.connection.state); /* check expected clientId */ - assertEquals("Auth#clientId is expected to be set", "options clientId", ablyRealtime.auth.clientId); + assertEquals("Auth#clientId is expected to be set", "options clientId", realtimeClient.auth.clientId); - ablyRealtime.close(); + realtimeClient.close(); } catch (AblyException e) { e.printStackTrace(); fail(); @@ -505,7 +508,7 @@ public void auth_client_null_match_tokendetails_wildcard_clientId() { try { /* init ably for token */ ClientOptions optsForToken = createOptions(testVars.keys[0].keyStr); - final AblyRest ablyForToken = new AblyRest(optsForToken); + final PubSubHttpClient ablyForToken = HttpClientFactory.create(optsForToken); /* get token */ Auth.TokenParams tokenParams = new Auth.TokenParams(); @@ -517,18 +520,18 @@ public void auth_client_null_match_tokendetails_wildcard_clientId() { ClientOptions opts = createOptions(); opts.clientId = null; opts.tokenDetails = tokenDetails; - AblyRealtime ablyRealtime = new AblyRealtime(opts); + PubSubRealtimeClient realtimeClient = RealtimeClientFactory.create(opts); System.out.println("done create ably"); /* wait for connected state */ - Helpers.ConnectionWaiter connectionWaiter = new Helpers.ConnectionWaiter(ablyRealtime.connection); + Helpers.ConnectionWaiter connectionWaiter = new Helpers.ConnectionWaiter(realtimeClient.connection); connectionWaiter.waitFor(ConnectionState.connected); - assertEquals("Verify connected state is reached", ConnectionState.connected, ablyRealtime.connection.state); + assertEquals("Verify connected state is reached", ConnectionState.connected, realtimeClient.connection.state); /* check expected clientId */ - assertEquals("Auth#clientId is expected to be set", "*", ablyRealtime.auth.clientId); + assertEquals("Auth#clientId is expected to be set", "*", realtimeClient.auth.clientId); - ablyRealtime.close(); + realtimeClient.close(); } catch (AblyException e) { e.printStackTrace(); fail(); @@ -549,7 +552,7 @@ public void auth_client_null_match_token_wildcard_clientId() { try { /* init ably for token */ ClientOptions optsForToken = createOptions(testVars.keys[0].keyStr); - final AblyRest ablyForToken = new AblyRest(optsForToken); + final PubSubHttpClient ablyForToken = HttpClientFactory.create(optsForToken); /* get token */ Auth.TokenParams tokenParams = new Auth.TokenParams(); @@ -561,18 +564,18 @@ public void auth_client_null_match_token_wildcard_clientId() { ClientOptions opts = createOptions(); opts.clientId = null; opts.token = tokenDetails.token; - AblyRealtime ablyRealtime = new AblyRealtime(opts); + PubSubRealtimeClient realtimeClient = RealtimeClientFactory.create(opts); System.out.println("done create ably"); /* wait for connected state */ - Helpers.ConnectionWaiter connectionWaiter = new Helpers.ConnectionWaiter(ablyRealtime.connection); + Helpers.ConnectionWaiter connectionWaiter = new Helpers.ConnectionWaiter(realtimeClient.connection); connectionWaiter.waitFor(ConnectionState.connected); - assertEquals("Verify connected state is reached", ConnectionState.connected, ablyRealtime.connection.state); + assertEquals("Verify connected state is reached", ConnectionState.connected, realtimeClient.connection.state); /* check expected clientId */ - assertEquals("Auth#clientId is expected to be set", "*", ablyRealtime.auth.clientId); + assertEquals("Auth#clientId is expected to be set", "*", realtimeClient.auth.clientId); - ablyRealtime.close(); + realtimeClient.close(); } catch (AblyException e) { e.printStackTrace(); fail(); @@ -591,7 +594,7 @@ public void auth_client_match_tokendetails_clientId() { try { /* init ably for token */ ClientOptions optsForToken = createOptions(testVars.keys[0].keyStr); - final AblyRest ablyForToken = new AblyRest(optsForToken); + final PubSubHttpClient ablyForToken = HttpClientFactory.create(optsForToken); /* get token */ Auth.TokenParams tokenParams = new Auth.TokenParams(); @@ -603,17 +606,17 @@ public void auth_client_match_tokendetails_clientId() { ClientOptions opts = createOptions(); opts.clientId = "options clientId"; opts.tokenDetails = tokenDetails; - AblyRealtime ablyRealtime = new AblyRealtime(opts); + PubSubRealtimeClient realtimeClient = RealtimeClientFactory.create(opts); /* wait for connected state */ - Helpers.ConnectionWaiter connectionWaiter = new Helpers.ConnectionWaiter(ablyRealtime.connection); + Helpers.ConnectionWaiter connectionWaiter = new Helpers.ConnectionWaiter(realtimeClient.connection); connectionWaiter.waitFor(ConnectionState.connected); - assertEquals("Verify connected state is reached", ConnectionState.connected, ablyRealtime.connection.state); + assertEquals("Verify connected state is reached", ConnectionState.connected, realtimeClient.connection.state); /* check expected clientId */ - assertEquals("Auth#clientId is expected to be set", "options clientId", ablyRealtime.auth.clientId); + assertEquals("Auth#clientId is expected to be set", "options clientId", realtimeClient.auth.clientId); - ablyRealtime.close(); + realtimeClient.close(); } catch (AblyException e) { e.printStackTrace(); fail(); @@ -632,7 +635,7 @@ public void auth_client_match_token_clientId() { try { /* init ably for token */ ClientOptions optsForToken = createOptions(testVars.keys[0].keyStr); - final AblyRest ablyForToken = new AblyRest(optsForToken); + final PubSubHttpClient ablyForToken = HttpClientFactory.create(optsForToken); /* get token */ Auth.TokenParams tokenParams = new Auth.TokenParams(); @@ -644,17 +647,17 @@ public void auth_client_match_token_clientId() { ClientOptions opts = createOptions(); opts.clientId = "options clientId"; opts.token = tokenDetails.token; - AblyRealtime ablyRealtime = new AblyRealtime(opts); + PubSubRealtimeClient realtimeClient = RealtimeClientFactory.create(opts); /* wait for connected state */ - Helpers.ConnectionWaiter connectionWaiter = new Helpers.ConnectionWaiter(ablyRealtime.connection); + Helpers.ConnectionWaiter connectionWaiter = new Helpers.ConnectionWaiter(realtimeClient.connection); connectionWaiter.waitFor(ConnectionState.connected); - assertEquals("Verify connected state is reached", ConnectionState.connected, ablyRealtime.connection.state); + assertEquals("Verify connected state is reached", ConnectionState.connected, realtimeClient.connection.state); /* check expected clientId */ - assertEquals("Auth#clientId is expected to be set", "options clientId", ablyRealtime.auth.clientId); + assertEquals("Auth#clientId is expected to be set", "options clientId", realtimeClient.auth.clientId); - ablyRealtime.close(); + realtimeClient.close(); } catch (AblyException e) { e.printStackTrace(); fail(); @@ -674,7 +677,7 @@ public void auth_client_match_tokendetails_clientId_fail() { try { /* init ably for token */ ClientOptions optsForToken = createOptions(testVars.keys[0].keyStr); - final AblyRest ablyForToken = new AblyRest(optsForToken); + final PubSubHttpClient ablyForToken = HttpClientFactory.create(optsForToken); /* get token */ Auth.TokenParams tokenParams = new Auth.TokenParams(); @@ -686,7 +689,7 @@ public void auth_client_match_tokendetails_clientId_fail() { ClientOptions opts = createOptions(); opts.clientId = "options clientId"; opts.tokenDetails = tokenDetails; - new AblyRealtime(opts); + RealtimeClientFactory.create(opts); } catch (AblyException e) { assertEquals("Verify error code indicates clientId mismatch", e.errorInfo.code, 40101); } @@ -706,7 +709,7 @@ public void auth_client_match_token_clientId_fail() { try { /* init ably for token */ ClientOptions optsForToken = createOptions(testVars.keys[0].keyStr); - final AblyRest ablyForToken = new AblyRest(optsForToken); + final PubSubHttpClient ablyForToken = HttpClientFactory.create(optsForToken); /* get token */ Auth.TokenParams tokenParams = new Auth.TokenParams(); @@ -718,12 +721,12 @@ public void auth_client_match_token_clientId_fail() { ClientOptions opts = createOptions(); opts.clientId = "options clientId"; opts.token = tokenDetails.token; - AblyRealtime ablyRealtime = new AblyRealtime(opts); + PubSubRealtimeClient realtimeClient = RealtimeClientFactory.create(opts); /* wait for failed state */ - Helpers.ConnectionWaiter connectionWaiter = new Helpers.ConnectionWaiter(ablyRealtime.connection); + Helpers.ConnectionWaiter connectionWaiter = new Helpers.ConnectionWaiter(realtimeClient.connection); ErrorInfo failure = connectionWaiter.waitFor(ConnectionState.failed); - assertEquals("Verify failed state is reached", ConnectionState.failed, ablyRealtime.connection.state); + assertEquals("Verify failed state is reached", ConnectionState.failed, realtimeClient.connection.state); assertEquals("Verify failure error code indicates clientId mismatch", failure.code, 40101); } catch (AblyException e) { e.printStackTrace(); @@ -747,7 +750,7 @@ public void auth_clientid_publish_implicit() { fillInOptions(options); options.clientId = clientId; options.protocolListener = protocolListener; - AblyRealtime ably = new AblyRealtime(options); + PubSubRealtimeClient ably = RealtimeClientFactory.create(options); /* wait until connected */ (new ConnectionWaiter(ably.connection)).waitFor(ConnectionState.connected); @@ -861,12 +864,12 @@ public void auth_clientid_publish_implicit() { @Ignore("FIXME: fix exception") @Test public void auth_clientid_publish_explicit_before_identified() { - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; try { String clientId = "test clientId"; ClientOptions optsForToken = createOptions(testVars.keys[0].keyStr); optsForToken.clientId = clientId; - AblyRest ablyForToken = new AblyRest(optsForToken); + PubSubHttpClient ablyForToken = HttpClientFactory.create(optsForToken); TokenDetails tokenDetails = ablyForToken.auth.requestToken(null, null); /* create Ably instance with token and implied clientId */ @@ -875,7 +878,7 @@ public void auth_clientid_publish_explicit_before_identified() { fillInOptions(options); options.token = tokenDetails.token; options.protocolListener = protocolListener; - ably = new AblyRealtime(options); + ably = RealtimeClientFactory.create(options); /* verify we don't yet know the implied clientId */ assertNull("Verify clientId is unknown", ably.auth.clientId); @@ -952,7 +955,7 @@ public void auth_renew_whilst_connecting() { /* get a TokenDetails */ final String testKey = testVars.keys[0].keyStr; ClientOptions optsForToken = createOptions(testKey); - final AblyRest ablyForToken = new AblyRest(optsForToken); + final PubSubHttpClient ablyForToken = HttpClientFactory.create(optsForToken); final TokenDetails tokenDetails = ablyForToken.auth.requestToken(new Auth.TokenParams(){{ ttl = 1000L; }}, null); assertNotNull("Expected token value", tokenDetails.token); @@ -989,13 +992,13 @@ public Object getTokenRequest(Auth.TokenParams params) { } }; - final AblyRealtime ably = new AblyRealtime(opts); + final PubSubRealtimeClient ably = RealtimeClientFactory.create(opts); synchronized (opts) { ably.connect(); try { opts.wait(); } catch(InterruptedException ignored) {} - ably.auth.renew(); + ably.auth.renewAuth((success, renewed, errorInfo) -> {}); } Helpers.ConnectionWaiter connectionWaiter = new Helpers.ConnectionWaiter(ably.connection); @@ -1022,7 +1025,7 @@ public void auth_renewAuth_whilst_connecting() { /* get a TokenDetails */ final String testKey = testVars.keys[0].keyStr; ClientOptions optsForToken = createOptions(testKey); - final AblyRest ablyForToken = new AblyRest(optsForToken); + final PubSubHttpClient ablyForToken = HttpClientFactory.create(optsForToken); final TokenDetails tokenDetails = ablyForToken.auth.requestToken(new Auth.TokenParams(){{ ttl = 1000L; }}, null); assertNotNull("Expected token value", tokenDetails.token); @@ -1059,7 +1062,7 @@ public Object getTokenRequest(Auth.TokenParams params) { } }; - final AblyRealtime ably = new AblyRealtime(opts); + final PubSubRealtimeClient ably = RealtimeClientFactory.create(opts); synchronized (opts) { ably.connect(); try { @@ -1092,9 +1095,9 @@ public void auth_renewAuth_callback_invoked() throws InterruptedException { /* get a TokenDetails */ final String testKey = testVars.keys[0].keyStr; final ClientOptions clientOptions = createOptions(testKey); - final AblyRest ablyRest = new AblyRest(clientOptions); + final PubSubHttpClient pubSubHttpClient = HttpClientFactory.create(clientOptions); - final TokenDetails tokenDetails = ablyRest.auth.requestToken(new Auth.TokenParams() {{ + final TokenDetails tokenDetails = pubSubHttpClient.auth.requestToken(new Auth.TokenParams() {{ ttl = 1000L; }}, null); assertNotNull("Expected token value", tokenDetails.token); @@ -1132,7 +1135,7 @@ public void onRawMessageRecv(ProtocolMessage message) { // implement callback, using Ably instance with key protocolListener.authCallback = params -> tokenDetails; - final AblyRealtime ably = new AblyRealtime(protocolListener); + final PubSubRealtimeClient ably = RealtimeClientFactory.create(protocolListener); synchronized (protocolListener) { ably.connect(); try { @@ -1175,7 +1178,7 @@ public void auth_expired_token_expire_before_connect_renew() { final String testKey = testVars.keys[0].keyStr; ClientOptions optsForToken = createOptions(testKey); optsForToken.queryTime = false; - final AblyRest ablyForToken = new AblyRest(optsForToken); + final PubSubHttpClient ablyForToken = HttpClientFactory.create(optsForToken); TokenDetails tokenDetails = ablyForToken.auth.requestToken(new Auth.TokenParams(){{ ttl = 100L; }}, null); assertNotNull("Expected token value", tokenDetails.token); @@ -1197,7 +1200,7 @@ public Object getTokenRequest(Auth.TokenParams params) throws AblyException { /* disable token validity check */ opts.queryTime = false; - final AblyRealtime ably = new AblyRealtime(opts); + final PubSubRealtimeClient ably = RealtimeClientFactory.create(opts); Helpers.ConnectionWaiter connectionWaiter = new Helpers.ConnectionWaiter(ably.connection); boolean isConnected = connectionWaiter.waitFor(ConnectionState.connected, 1, 30000L); @@ -1225,7 +1228,7 @@ public void auth_expired_token_expire_after_connect_renew() { final String testKey = testVars.keys[0].keyStr; ClientOptions optsForToken = createOptions(testKey); optsForToken.queryTime = true; - final AblyRest ablyForToken = new AblyRest(optsForToken); + final PubSubHttpClient ablyForToken = HttpClientFactory.create(optsForToken); TokenDetails tokenDetails = ablyForToken.auth.requestToken(new Auth.TokenParams(){{ ttl = 2000L; }}, null); assertNotNull("Expected token value", tokenDetails.token); @@ -1241,7 +1244,7 @@ public Object getTokenRequest(Auth.TokenParams params) throws AblyException { } }; - final AblyRealtime ably = new AblyRealtime(opts); + final PubSubRealtimeClient ably = RealtimeClientFactory.create(opts); Helpers.ConnectionWaiter connectionWaiter = new Helpers.ConnectionWaiter(ably.connection); if(connectionWaiter.waitFor(ConnectionState.connected, 2, 4000L)) { diff --git a/lib/src/test/java/io/ably/lib/test/realtime/RealtimeChannelHistoryTest.java b/lib/src/test/java/io/ably/pubsub/test/realtime/RealtimeChannelHistoryTest.java similarity index 94% rename from lib/src/test/java/io/ably/lib/test/realtime/RealtimeChannelHistoryTest.java rename to lib/src/test/java/io/ably/pubsub/test/realtime/RealtimeChannelHistoryTest.java index b11439ff4..9ac693679 100644 --- a/lib/src/test/java/io/ably/lib/test/realtime/RealtimeChannelHistoryTest.java +++ b/lib/src/test/java/io/ably/pubsub/test/realtime/RealtimeChannelHistoryTest.java @@ -1,4 +1,4 @@ -package io.ably.lib.test.realtime; +package io.ably.pubsub.test.realtime; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.is; @@ -18,24 +18,25 @@ import org.junit.Test; import org.junit.rules.Timeout; -import io.ably.lib.realtime.AblyRealtime; -import io.ably.lib.realtime.Channel; -import io.ably.lib.realtime.ChannelState; -import io.ably.lib.test.common.Helpers.ChannelWaiter; -import io.ably.lib.test.common.Helpers.CompletionSet; -import io.ably.lib.test.common.Helpers.CompletionWaiter; -import io.ably.lib.test.common.Helpers.MessageWaiter; -import io.ably.lib.test.common.ParameterizedTest; -import io.ably.lib.types.AblyException; -import io.ably.lib.types.ClientOptions; -import io.ably.lib.types.Message; -import io.ably.lib.types.PaginatedResult; -import io.ably.lib.types.Param; +import io.ably.pubsub.realtime.PubSubRealtimeClient; +import io.ably.pubsub.realtime.RealtimeClientFactory; +import io.ably.pubsub.realtime.Channel; +import io.ably.pubsub.realtime.ChannelState; +import io.ably.pubsub.test.common.Helpers.ChannelWaiter; +import io.ably.pubsub.test.common.Helpers.CompletionSet; +import io.ably.pubsub.test.common.Helpers.CompletionWaiter; +import io.ably.pubsub.test.common.Helpers.MessageWaiter; +import io.ably.pubsub.test.common.ParameterizedTest; +import io.ably.pubsub.types.AblyException; +import io.ably.pubsub.types.ClientOptions; +import io.ably.pubsub.types.Message; +import io.ably.pubsub.types.PaginatedResult; +import io.ably.pubsub.types.Param; @Ignore("FIXME: fix exceptions") public class RealtimeChannelHistoryTest extends ParameterizedTest { - private AblyRealtime ably; + private PubSubRealtimeClient ably; private long timeOffset; @Rule @@ -44,7 +45,7 @@ public class RealtimeChannelHistoryTest extends ParameterizedTest { @Before public void setUpBefore() throws Exception { ClientOptions opts = createOptions(testVars.keys[0].keyStr); - ably = new AblyRealtime(opts); + ably = RealtimeClientFactory.create(opts); long timeFromService = ably.time(); timeOffset = timeFromService - System.currentTimeMillis(); } @@ -56,10 +57,10 @@ public void setUpBefore() throws Exception { */ @Test public void channelhistory_simple() { - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; try { ClientOptions opts = createOptions(testVars.keys[0].keyStr); - ably = new AblyRealtime(opts); + ably = RealtimeClientFactory.create(opts); String channelName = "persisted:channelhistory_simple_" + testParams.name; String messageText = "Test message (channelhistory_simple)"; @@ -102,10 +103,10 @@ public void channelhistory_simple() { */ @Test public void channelhistory_simple_withoutlistener() { - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; try { ClientOptions opts = createOptions(testVars.keys[0].keyStr); - ably = new AblyRealtime(opts); + ably = RealtimeClientFactory.create(opts); String channelName = "persisted:channelhistory_simple_withoutlistener_" + testParams.name; String message1Text = "Test message 1 (channelhistory_simple_withoutlistener)"; Message message2 = new Message("test_event", "Test message 2 (channelhistory_simple_withoutlistener)"); @@ -159,10 +160,10 @@ public void channelhistory_simple_withoutlistener() { */ @Test public void channelhistory_types() { - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; try { ClientOptions opts = createOptions(testVars.keys[0].keyStr); - ably = new AblyRealtime(opts); + ably = RealtimeClientFactory.create(opts); String channelName = "persisted:channelhistory_types_" + testParams.name; /* create a channel */ @@ -214,10 +215,10 @@ public void channelhistory_types() { */ @Test public void channelhistory_types_forward() { - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; try { ClientOptions opts = createOptions(testVars.keys[0].keyStr); - ably = new AblyRealtime(opts); + ably = RealtimeClientFactory.create(opts); String channelName = "persisted:channelhistory_types_forward_" + testParams.name; /* create a channel */ @@ -272,12 +273,12 @@ public void channelhistory_types_forward() { */ @Test public void channelhistory_second_channel() { - AblyRealtime txAbly = null, rxAbly = null; + PubSubRealtimeClient txAbly = null, rxAbly = null; try { ClientOptions txOpts = createOptions(testVars.keys[0].keyStr); - txAbly = new AblyRealtime(txOpts); + txAbly = RealtimeClientFactory.create(txOpts); ClientOptions rxOpts = createOptions(testVars.keys[0].keyStr); - rxAbly = new AblyRealtime(rxOpts); + rxAbly = RealtimeClientFactory.create(rxOpts); String channelName = "persisted:channelhistory_second_channel_" + testParams.name; /* create a channel */ @@ -329,10 +330,10 @@ public void channelhistory_second_channel() { */ @Test public void channelhistory_wait_b() { - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; try { ClientOptions opts = createOptions(testVars.keys[0].keyStr); - ably = new AblyRealtime(opts); + ably = RealtimeClientFactory.create(opts); String channelName = "persisted:channelhistory_wait_b_" + testParams.name; String messageText = "Test message (channelhistory_wait_b)"; @@ -380,10 +381,10 @@ public void channelhistory_wait_b() { */ @Test public void channelhistory_wait_f() { - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; try { ClientOptions opts = createOptions(testVars.keys[0].keyStr); - ably = new AblyRealtime(opts); + ably = RealtimeClientFactory.create(opts); String channelName = "persisted:channelhistory_wait_f_" + testParams.name; String messageText = "Test message (channelhistory_wait_f)"; @@ -431,10 +432,10 @@ public void channelhistory_wait_f() { */ @Test public void channelhistory_mixed_b() { - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; try { ClientOptions opts = createOptions(testVars.keys[0].keyStr); - ably = new AblyRealtime(opts); + ably = RealtimeClientFactory.create(opts); String channelName = "persisted:channelhistory_mixed_b_" + testParams.name; String messageText = "Test message (channelhistory_mixed_b)"; String persistEventName = "test_event (persisted)"; @@ -493,10 +494,10 @@ public void channelhistory_mixed_b() { */ @Test public void channelhistory_mixed_f() { - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; try { ClientOptions opts = createOptions(testVars.keys[0].keyStr); - ably = new AblyRealtime(opts); + ably = RealtimeClientFactory.create(opts); String channelName = "persisted:channelhistory_mixed_f_" + testParams.name; String messageText = "Test message (channelhistory_mixed_f)"; String persistEventName = "test_event (persisted)"; @@ -552,10 +553,10 @@ public void channelhistory_mixed_f() { */ @Test public void channelhistory_limit_f() { - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; try { ClientOptions opts = createOptions(testVars.keys[0].keyStr); - ably = new AblyRealtime(opts); + ably = RealtimeClientFactory.create(opts); String channelName = "persisted:channelhistory_limit_f_" + testParams.name; /* create a channel */ @@ -608,10 +609,10 @@ public void channelhistory_limit_f() { */ @Test public void channelhistory_limit_b() { - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; try { ClientOptions opts = createOptions(testVars.keys[0].keyStr); - ably = new AblyRealtime(opts); + ably = RealtimeClientFactory.create(opts); String channelName = "persisted:channelhistory_limit_b_" + testParams.name; /* create a channel */ @@ -665,12 +666,12 @@ public void channelhistory_limit_b() { */ @Test public void channelhistory_time_f() { - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; try { /* first, publish some messages */ long intervalStart = 0, intervalEnd = 0; ClientOptions opts = createOptions(testVars.keys[0].keyStr); - ably = new AblyRealtime(opts); + ably = RealtimeClientFactory.create(opts); String channelName = "persisted:channelhistory_time_f_" + testParams.name; /* create a channel */ @@ -733,12 +734,12 @@ public void channelhistory_time_f() { */ @Test public void channelhistory_time_b() { - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; try { /* first, publish some messages */ long intervalStart = 0, intervalEnd = 0; ClientOptions opts = createOptions(testVars.keys[0].keyStr); - ably = new AblyRealtime(opts); + ably = RealtimeClientFactory.create(opts); String channelName = "persisted:channelhistory_time_b_" + testParams.name; /* create a channel */ @@ -801,10 +802,10 @@ public void channelhistory_time_b() { */ @Test public void channelhistory_paginate_f() { - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; try { ClientOptions opts = createOptions(testVars.keys[0].keyStr); - ably = new AblyRealtime(opts); + ably = RealtimeClientFactory.create(opts); String channelName = "persisted:channelhistory_paginate_f_" + testParams.name; /* create a channel */ @@ -889,10 +890,10 @@ public void channelhistory_paginate_f() { */ @Test public void channelhistory_paginate_b() { - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; try { ClientOptions opts = createOptions(testVars.keys[0].keyStr); - ably = new AblyRealtime(opts); + ably = RealtimeClientFactory.create(opts); String channelName = "persisted:channelhistory_paginate_b_" + testParams.name; /* create a channel */ @@ -977,10 +978,10 @@ public void channelhistory_paginate_b() { */ @Test public void channelhistory_paginate_first_f() { - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; try { ClientOptions opts = createOptions(testVars.keys[0].keyStr); - ably = new AblyRealtime(opts); + ably = RealtimeClientFactory.create(opts); String channelName = "persisted:channelhistory_paginate_first_f_" + testParams.name; /* create a channel */ @@ -1065,10 +1066,10 @@ public void channelhistory_paginate_first_f() { */ @Test public void channelhistory_paginate_first_b() { - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; try { ClientOptions opts = createOptions(testVars.keys[0].keyStr); - ably = new AblyRealtime(opts); + ably = RealtimeClientFactory.create(opts); String channelName = "persisted:channelhistory_paginate_first_b_" + testParams.name; /* create a channel */ @@ -1157,12 +1158,12 @@ public void channelhistory_paginate_first_b() { @Test @Ignore("Fails due to issues in sandbox. See https://github.com/ably/realtime/issues/1834 for details.") public void channelhistory_from_attach() { - AblyRealtime txAbly = null, rxAbly = null; + PubSubRealtimeClient txAbly = null, rxAbly = null; try { ClientOptions txOpts = createOptions(testVars.keys[0].keyStr); - txAbly = new AblyRealtime(txOpts); + txAbly = RealtimeClientFactory.create(txOpts); ClientOptions rxOpts = createOptions(testVars.keys[0].keyStr); - rxAbly = new AblyRealtime(rxOpts); + rxAbly = RealtimeClientFactory.create(rxOpts); String channelName = "persisted:channelhistory_from_attach_" + testParams.name; /* create a channel */ @@ -1247,12 +1248,12 @@ public void run() { */ @Test public void channelhistory_until_attach() { - AblyRealtime txAbly = null, rxAbly = null; + PubSubRealtimeClient txAbly = null, rxAbly = null; try { ClientOptions txOpts = createOptions(testVars.keys[0].keyStr); - txAbly = new AblyRealtime(txOpts); + txAbly = RealtimeClientFactory.create(txOpts); ClientOptions rxOpts = createOptions(testVars.keys[0].keyStr); - rxAbly = new AblyRealtime(rxOpts); + rxAbly = RealtimeClientFactory.create(rxOpts); String channelName = "persisted:channelhistory_until_attach_" + testParams.name; /* create a channel */ @@ -1315,7 +1316,7 @@ public void channelhistory_until_attach() { @Test(expected=AblyException.class) public void channelhistory_until_attach_before_attached() throws AblyException { ClientOptions options = createOptions(testVars.keys[0].keyStr); - AblyRealtime ably = new AblyRealtime(options); + PubSubRealtimeClient ably = RealtimeClientFactory.create(options); ably.channels.get("test").history(new Param[]{ new Param("untilAttach", "true") }); } @@ -1329,7 +1330,7 @@ public void channelhistory_until_attach_before_attached() throws AblyException { @Test(expected=AblyException.class) public void channelhistory_until_attach_invalid_value() throws AblyException { ClientOptions options = createOptions(testVars.keys[0].keyStr); - AblyRealtime ably = new AblyRealtime(options); + PubSubRealtimeClient ably = RealtimeClientFactory.create(options); ably.channels.get("test").history(new Param[]{ new Param("untilAttach", "affirmative")}); } @@ -1342,10 +1343,10 @@ public void channelhistory_until_attach_invalid_value() throws AblyException { */ @Test public void channelhistory_islast() throws AblyException { - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; try { ClientOptions opts = createOptions(testVars.keys[0].keyStr); - ably = new AblyRealtime(opts); + ably = RealtimeClientFactory.create(opts); String channelName = "persisted:channelhistory_islast_" + testParams.name; int pageMessageCount = 10; diff --git a/lib/src/test/java/io/ably/lib/test/realtime/RealtimeChannelMessageEditTest.java b/lib/src/test/java/io/ably/pubsub/test/realtime/RealtimeChannelMessageEditTest.java similarity index 95% rename from lib/src/test/java/io/ably/lib/test/realtime/RealtimeChannelMessageEditTest.java rename to lib/src/test/java/io/ably/pubsub/test/realtime/RealtimeChannelMessageEditTest.java index 7d06a5f24..844549904 100644 --- a/lib/src/test/java/io/ably/lib/test/realtime/RealtimeChannelMessageEditTest.java +++ b/lib/src/test/java/io/ably/pubsub/test/realtime/RealtimeChannelMessageEditTest.java @@ -1,20 +1,21 @@ -package io.ably.lib.test.realtime; - -import io.ably.lib.realtime.AblyRealtime; -import io.ably.lib.realtime.Channel; -import io.ably.lib.test.common.Helpers; -import io.ably.lib.test.common.ParameterizedTest; -import io.ably.lib.types.AblyException; -import io.ably.lib.types.ChannelOptions; -import io.ably.lib.types.ClientOptions; -import io.ably.lib.types.Message; -import io.ably.lib.types.MessageAction; -import io.ably.lib.types.MessageOperation; -import io.ably.lib.types.PaginatedResult; -import io.ably.lib.types.Param; -import io.ably.lib.types.PublishResult; -import io.ably.lib.types.UpdateDeleteResult; -import io.ably.lib.util.Crypto; +package io.ably.pubsub.test.realtime; + +import io.ably.pubsub.realtime.PubSubRealtimeClient; +import io.ably.pubsub.realtime.RealtimeClientFactory; +import io.ably.pubsub.realtime.Channel; +import io.ably.pubsub.test.common.Helpers; +import io.ably.pubsub.test.common.ParameterizedTest; +import io.ably.pubsub.types.AblyException; +import io.ably.pubsub.types.ChannelOptions; +import io.ably.pubsub.types.ClientOptions; +import io.ably.pubsub.types.Message; +import io.ably.pubsub.types.MessageAction; +import io.ably.pubsub.types.MessageOperation; +import io.ably.pubsub.types.PaginatedResult; +import io.ably.pubsub.types.Param; +import io.ably.pubsub.types.PublishResult; +import io.ably.pubsub.types.UpdateDeleteResult; +import io.ably.pubsub.util.Crypto; import org.junit.After; import org.junit.Before; import org.junit.Rule; @@ -38,12 +39,12 @@ public class RealtimeChannelMessageEditTest extends ParameterizedTest { @Rule public Timeout testTimeout = Timeout.seconds(300); - private AblyRealtime ably; + private PubSubRealtimeClient ably; @Before public void setUpBefore() throws Exception { ClientOptions opts = createOptions(testVars.keys[0].keyStr); - ably = new AblyRealtime(opts); + ably = RealtimeClientFactory.create(opts); } @After diff --git a/lib/src/test/java/io/ably/lib/test/realtime/RealtimeChannelTest.java b/lib/src/test/java/io/ably/pubsub/test/realtime/RealtimeChannelTest.java similarity index 93% rename from lib/src/test/java/io/ably/lib/test/realtime/RealtimeChannelTest.java rename to lib/src/test/java/io/ably/pubsub/test/realtime/RealtimeChannelTest.java index 8fa2a3bbc..529ac9458 100644 --- a/lib/src/test/java/io/ably/lib/test/realtime/RealtimeChannelTest.java +++ b/lib/src/test/java/io/ably/pubsub/test/realtime/RealtimeChannelTest.java @@ -1,30 +1,31 @@ -package io.ably.lib.test.realtime; - -import io.ably.lib.debug.DebugOptions; -import io.ably.lib.realtime.AblyRealtime; -import io.ably.lib.realtime.Channel; -import io.ably.lib.realtime.Channel.MessageListener; -import io.ably.lib.realtime.ChannelEvent; -import io.ably.lib.realtime.ChannelState; -import io.ably.lib.realtime.ChannelStateListener; -import io.ably.lib.realtime.ConnectionEvent; -import io.ably.lib.realtime.CompletionListener; -import io.ably.lib.realtime.ConnectionState; -import io.ably.lib.test.common.Helpers; -import io.ably.lib.test.common.Helpers.ChannelWaiter; -import io.ably.lib.test.common.Helpers.ConnectionWaiter; -import io.ably.lib.test.common.ParameterizedTest; -import io.ably.lib.test.util.MockWebsocketFactory; -import io.ably.lib.transport.ConnectionManager; -import io.ably.lib.transport.Defaults; -import io.ably.lib.types.AblyException; -import io.ably.lib.types.ChannelMode; -import io.ably.lib.types.ChannelOptions; -import io.ably.lib.types.ClientOptions; -import io.ably.lib.types.ErrorInfo; -import io.ably.lib.types.Message; -import io.ably.lib.types.ProtocolMessage; -import io.ably.lib.util.Log; +package io.ably.pubsub.test.realtime; + +import io.ably.pubsub.debug.DebugOptions; +import io.ably.pubsub.realtime.PubSubRealtimeClient; +import io.ably.pubsub.realtime.RealtimeClientFactory; +import io.ably.pubsub.realtime.Channel; +import io.ably.pubsub.realtime.Channel.MessageListener; +import io.ably.pubsub.realtime.ChannelEvent; +import io.ably.pubsub.realtime.ChannelState; +import io.ably.pubsub.realtime.ChannelStateListener; +import io.ably.pubsub.realtime.ConnectionEvent; +import io.ably.pubsub.realtime.CompletionListener; +import io.ably.pubsub.realtime.ConnectionState; +import io.ably.pubsub.test.common.Helpers; +import io.ably.pubsub.test.common.Helpers.ChannelWaiter; +import io.ably.pubsub.test.common.Helpers.ConnectionWaiter; +import io.ably.pubsub.test.common.ParameterizedTest; +import io.ably.pubsub.test.util.MockWebsocketFactory; +import io.ably.pubsub.transport.ConnectionManager; +import io.ably.pubsub.transport.Defaults; +import io.ably.pubsub.types.AblyException; +import io.ably.pubsub.types.ChannelMode; +import io.ably.pubsub.types.ChannelOptions; +import io.ably.pubsub.types.ClientOptions; +import io.ably.pubsub.types.ErrorInfo; +import io.ably.pubsub.types.Message; +import io.ably.pubsub.types.ProtocolMessage; +import io.ably.pubsub.util.Log; import org.hamcrest.Matchers; import org.junit.Assert; import org.junit.Ignore; @@ -71,10 +72,10 @@ public int compare(Message o1, Message o2) { @Test public void attach() { String channelName = "attach_" + testParams.name; - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; try { ClientOptions opts = createOptions(testVars.keys[0].keyStr); - ably = new AblyRealtime(opts); + ably = RealtimeClientFactory.create(opts); /* wait until connected */ (new ConnectionWaiter(ably.connection)).waitFor(ConnectionState.connected); @@ -102,10 +103,10 @@ public void attach() { @Test public void attach_before_connect() { String channelName = "attach_before_connect_" + testParams.name; - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; try { ClientOptions opts = createOptions(testVars.keys[0].keyStr); - ably = new AblyRealtime(opts); + ably = RealtimeClientFactory.create(opts); /* create a channel and attach */ final Channel channel = ably.channels.get(channelName); @@ -129,10 +130,10 @@ public void attach_before_connect() { @Test public void attach_detach() { String channelName = "attach_detach_" + testParams.name; - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; try { ClientOptions opts = createOptions(testVars.keys[0].keyStr); - ably = new AblyRealtime(opts); + ably = RealtimeClientFactory.create(opts); /* create a channel and attach */ final Channel channel = ably.channels.get(channelName); @@ -157,10 +158,10 @@ public void attach_detach() { @Test public void attach_with_channel_params_channels_get() { String channelName = "attach_with_channel_params_channels_get_" + testParams.name; - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; try { ClientOptions opts = createOptions(testVars.keys[0].keyStr); - ably = new AblyRealtime(opts); + ably = RealtimeClientFactory.create(opts); /* wait until connected */ (new ConnectionWaiter(ably.connection)).waitFor(ConnectionState.connected); @@ -190,10 +191,10 @@ public void attach_with_channel_params_channels_get() { @Test public void attach_with_channel_params_set_options() { String channelName = "attach_with_channel_params_set_options_" + testParams.name; - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; try { ClientOptions opts = createOptions(testVars.keys[0].keyStr); - ably = new AblyRealtime(opts); + ably = RealtimeClientFactory.create(opts); /* wait until connected */ (new ConnectionWaiter(ably.connection)).waitFor(ConnectionState.connected); @@ -224,10 +225,10 @@ public void attach_with_channel_params_set_options() { @Test public void channels_get_should_throw_when_would_cause_reattach() { String channelName = "channels_get_should_throw_when_would_cause_reattach_" + testParams.name; - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; try { ClientOptions opts = createOptions(testVars.keys[0].keyStr); - ably = new AblyRealtime(opts); + ably = RealtimeClientFactory.create(opts); /* wait until connected */ (new ConnectionWaiter(ably.connection)).waitFor(ConnectionState.connected); @@ -244,7 +245,7 @@ public void channels_get_should_throw_when_would_cause_reattach() { channel.attach(); (new ChannelWaiter(channel)).waitFor(ChannelState.attached); - AblyRealtime finalAbly = ably; + PubSubRealtimeClient finalAbly = ably; AblyException exception = assertThrows(AblyException.class, () -> finalAbly.channels.get(channelName, options)); @@ -264,10 +265,10 @@ public void channels_get_should_throw_when_would_cause_reattach() { @Test public void attach_with_channel_params_modes_and_channel_modes() { String channelName = "attach_with_channel_params_modes_and_channel_modes_" + testParams.name; - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; try { ClientOptions opts = createOptions(testVars.keys[0].keyStr); - ably = new AblyRealtime(opts); + ably = RealtimeClientFactory.create(opts); /* wait until connected */ (new ConnectionWaiter(ably.connection)).waitFor(ConnectionState.connected); @@ -303,10 +304,10 @@ public void attach_with_channel_params_modes_and_channel_modes() { @Test public void attach_with_channel_modes() { String channelName = "attach_with_channel_modes_" + testParams.name; - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; try { ClientOptions opts = createOptions(testVars.keys[0].keyStr); - ably = new AblyRealtime(opts); + ably = RealtimeClientFactory.create(opts); /* wait until connected */ (new ConnectionWaiter(ably.connection)).waitFor(ConnectionState.connected); @@ -340,10 +341,10 @@ public void attach_with_channel_modes() { @Test public void attach_with_params_delta_and_channel_modes() { String channelName = "attach_with_params_delta_and_channel_modes_" + testParams.name; - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; try { ClientOptions opts = createOptions(testVars.keys[0].keyStr); - ably = new AblyRealtime(opts); + ably = RealtimeClientFactory.create(opts); /* wait until connected */ (new ConnectionWaiter(ably.connection)).waitFor(ConnectionState.connected); @@ -383,10 +384,10 @@ public void attach_with_params_delta_and_channel_modes() { @Test public void subscribe_unsubscribe() { String channelName = "subscribe_unsubscribe_" + testParams.name; - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; try { ClientOptions opts = createOptions(testVars.keys[0].keyStr); - ably = new AblyRealtime(opts); + ably = RealtimeClientFactory.create(opts); /* create a channel and attach */ final Channel channel = ably.channels.get(channelName); @@ -421,10 +422,10 @@ public void onMessage(Message message) { @Test public void subscribe_without_implicit_attach() { String channelName = "subscribe_" + testParams.name; - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; try { ClientOptions opts = createOptions(testVars.keys[0].keyStr); - ably = new AblyRealtime(opts); + ably = RealtimeClientFactory.create(opts); /* create a channel and set attachOnSubscribe to false */ final Channel channel = ably.channels.get(channelName); @@ -489,9 +490,9 @@ public void subscribe_without_implicit_attach() { @Test public void unsubscribe_all() throws AblyException { /* Ably instance that will emit messages */ - AblyRealtime ably1 = null; + PubSubRealtimeClient ably1 = null; /* Ably instance that will receive messages */ - AblyRealtime ably2 = null; + PubSubRealtimeClient ably2 = null; String channelName = "test.channel.unsubscribe.all" + System.currentTimeMillis(); Message[] messages = new Message[] { @@ -507,8 +508,8 @@ public void unsubscribe_all() throws AblyException { ClientOptions option2 = createOptions(testVars.keys[0].keyStr); option2.clientId = "receiver client"; - ably1 = new AblyRealtime(option1); - ably2 = new AblyRealtime(option2); + ably1 = RealtimeClientFactory.create(option1); + ably2 = RealtimeClientFactory.create(option2); Channel channel1 = ably1.channels.get(channelName); channel1.attach(); @@ -567,9 +568,9 @@ public MessageListener setMessageStack(List messageStack) { @Test public void unsubscribe_single() throws AblyException { /* Ably instance that will emit messages */ - AblyRealtime ably1 = null; + PubSubRealtimeClient ably1 = null; /* Ably instance that will receive messages */ - AblyRealtime ably2 = null; + PubSubRealtimeClient ably2 = null; String channelName = "test.channel.unsubscribe.single" + System.currentTimeMillis(); Message[] messages = new Message[] { @@ -585,8 +586,8 @@ public void unsubscribe_single() throws AblyException { ClientOptions option2 = createOptions(testVars.keys[0].keyStr); option2.clientId = "receiver client"; - ably1 = new AblyRealtime(option1); - ably2 = new AblyRealtime(option2); + ably1 = RealtimeClientFactory.create(option1); + ably2 = RealtimeClientFactory.create(option2); Channel channel1 = ably1.channels.get(channelName); channel1.attach(); @@ -646,9 +647,9 @@ public MessageListener setMessageStack(List messageStack) { @Test public void subscribe_all() throws AblyException { /* Ably instance that will emit channel messages */ - AblyRealtime ably1 = null; + PubSubRealtimeClient ably1 = null; /* Ably instance that will receive channel messages */ - AblyRealtime ably2 = null; + PubSubRealtimeClient ably2 = null; String channelName = "test.channel.subscribe.all" + System.currentTimeMillis(); Message[] messages = new Message[]{ @@ -663,8 +664,8 @@ public void subscribe_all() throws AblyException { ClientOptions option2 = createOptions(testVars.keys[0].keyStr); option2.clientId = "receiver client"; - ably1 = new AblyRealtime(option1); - ably2 = new AblyRealtime(option2); + ably1 = RealtimeClientFactory.create(option1); + ably2 = RealtimeClientFactory.create(option2); Channel channel1 = ably1.channels.get(channelName); channel1.attach(); @@ -730,9 +731,9 @@ public MessageListener setMessageStack(List messageStack) { @Test public void subscribe_multiple() throws AblyException { /* Ably instance that will emit channel messages */ - AblyRealtime ably1 = null; + PubSubRealtimeClient ably1 = null; /* Ably instance that will receive channel messages */ - AblyRealtime ably2 = null; + PubSubRealtimeClient ably2 = null; String channelName = "test.channel.subscribe.multiple" + System.currentTimeMillis(); Message[] messages = new Message[] { @@ -753,8 +754,8 @@ public void subscribe_multiple() throws AblyException { ClientOptions option2 = createOptions(testVars.keys[0].keyStr); option2.clientId = "receiver client"; - ably1 = new AblyRealtime(option1); - ably2 = new AblyRealtime(option2); + ably1 = RealtimeClientFactory.create(option1); + ably2 = RealtimeClientFactory.create(option2); Channel channel1 = ably1.channels.get(channelName); channel1.attach(); @@ -821,9 +822,9 @@ public MessageListener setMessageStack(List messageStack) { @Test public void subscribe_single() throws AblyException { /* Ably instance that will emit channel messages */ - AblyRealtime ably1 = null; + PubSubRealtimeClient ably1 = null; /* Ably instance that will receive channel messages */ - AblyRealtime ably2 = null; + PubSubRealtimeClient ably2 = null; String channelName = "test.channel.subscribe.single" + System.currentTimeMillis(); String messageName = "name"; @@ -839,8 +840,8 @@ public void subscribe_single() throws AblyException { ClientOptions option2 = createOptions(testVars.keys[0].keyStr); option2.clientId = "receiver client"; - ably1 = new AblyRealtime(option1); - ably2 = new AblyRealtime(option2); + ably1 = RealtimeClientFactory.create(option1); + ably2 = RealtimeClientFactory.create(option2); Channel channel1 = ably1.channels.get(channelName); channel1.attach(); @@ -903,10 +904,10 @@ public MessageListener setMessageStack(List messageStack) { */ @Test public void attach_fail() { - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; try { ClientOptions opts = createOptions(testVars.keys[1].keyStr); - ably = new AblyRealtime(opts); + ably = RealtimeClientFactory.create(opts); /* wait until connected */ (new ConnectionWaiter(ably.connection)).waitFor(ConnectionState.connected); @@ -934,10 +935,10 @@ public void attach_fail() { */ @Test public void attach_success_callback() { - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; try { ClientOptions opts = createOptions(testVars.keys[0].keyStr); - ably = new AblyRealtime(opts); + ably = RealtimeClientFactory.create(opts); /* wait until connected */ (new ConnectionWaiter(ably.connection)).waitFor(ConnectionState.connected); @@ -967,10 +968,10 @@ public void attach_success_callback() { */ @Test public void attach_success_callback_for_channel_in_failed_state() { - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; try { ClientOptions opts = createOptions(testVars.keys[0].keyStr); - ably = new AblyRealtime(opts); + ably = RealtimeClientFactory.create(opts); /* wait until connected */ (new ConnectionWaiter(ably.connection)).waitFor(ConnectionState.connected); @@ -1026,10 +1027,10 @@ public void attach_success_callback_for_channel_in_failed_state() { */ @Test public void attach_fail_callback() { - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; try { ClientOptions opts = createOptions(testVars.keys[1].keyStr); - ably = new AblyRealtime(opts); + ably = RealtimeClientFactory.create(opts); /* wait until connected */ (new ConnectionWaiter(ably.connection)).waitFor(ConnectionState.connected); @@ -1062,10 +1063,10 @@ public void attach_fail_callback() { */ @Test public void detach_success_callback_initialized() { - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; try { ClientOptions opts = createOptions(testVars.keys[0].keyStr); - ably = new AblyRealtime(opts); + ably = RealtimeClientFactory.create(opts); /* wait until connected */ (new ConnectionWaiter(ably.connection)).waitFor(ConnectionState.connected); @@ -1096,10 +1097,10 @@ public void detach_success_callback_initialized() { */ @Test public void detach_success_callback_on_suspended_state() { - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; try { ClientOptions opts = createOptions(testVars.keys[0].keyStr); - ably = new AblyRealtime(opts); + ably = RealtimeClientFactory.create(opts); /* wait until connected */ (new ConnectionWaiter(ably.connection)).waitFor(ConnectionState.connected); @@ -1136,10 +1137,10 @@ public void detach_success_callback_on_suspended_state() { */ @Test public void detach_failure_callback_on_failed_state() { - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; try { ClientOptions opts = createOptions(testVars.keys[0].keyStr); - ably = new AblyRealtime(opts); + ably = RealtimeClientFactory.create(opts); /* wait until connected */ (new ConnectionWaiter(ably.connection)).waitFor(ConnectionState.connected); @@ -1181,10 +1182,10 @@ public void detach_failure_callback_on_failed_state() { */ @Test public void detach_fail_callback_for_connection_invalid_state() { - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; try { ClientOptions opts = createOptions(testVars.keys[0].keyStr); - ably = new AblyRealtime(opts); + ably = RealtimeClientFactory.create(opts); ConnectionWaiter connWaiter = new ConnectionWaiter(ably.connection); /* wait until connected */ @@ -1254,10 +1255,10 @@ public void detach_fail_callback_for_connection_invalid_state() { */ @Test public void detach_success_callback_attached() throws AblyException { - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; try { ClientOptions opts = createOptions(testVars.keys[0].keyStr); - ably = new AblyRealtime(opts); + ably = RealtimeClientFactory.create(opts); /* wait until connected */ (new ConnectionWaiter(ably.connection)).waitFor(ConnectionState.connected); @@ -1289,10 +1290,10 @@ public void detach_success_callback_attached() throws AblyException { */ @Test public void detach_success_callback_detaching() throws AblyException { - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; try { ClientOptions opts = createOptions(testVars.keys[0].keyStr); - ably = new AblyRealtime(opts); + ably = RealtimeClientFactory.create(opts); /* wait until connected */ (new ConnectionWaiter(ably.connection)).waitFor(ConnectionState.connected); @@ -1329,13 +1330,13 @@ public void detach_success_callback_detaching() throws AblyException { // https://github.com/ably/ably-java/issues/885 @Test public void attach_when_channel_in_detaching_state() throws AblyException { - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; try { final DebugOptions opts = createOptions(testVars.keys[0].keyStr); final MockWebsocketFactory transportFactory = new MockWebsocketFactory(); opts.transportFactory = transportFactory; opts.logLevel = Log.VERBOSE; - ably = new AblyRealtime(opts); + ably = RealtimeClientFactory.create(opts); /* wait until connected */ (new ConnectionWaiter(ably.connection)).waitFor(ConnectionState.connected); @@ -1385,11 +1386,11 @@ public void attach_when_channel_in_detaching_state() throws AblyException { // https://github.com/ably/ably-java/issues/885 @Test public void detach_when_channel_in_attaching_state() throws AblyException { - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; try { ClientOptions opts = createOptions(testVars.keys[0].keyStr); opts.logLevel = Log.VERBOSE; - ably = new AblyRealtime(opts); + ably = RealtimeClientFactory.create(opts); /* wait until connected */ (new ConnectionWaiter(ably.connection)).waitFor(ConnectionState.connected); @@ -1426,10 +1427,10 @@ public void detach_when_channel_in_attaching_state() throws AblyException { */ @Test public void detach_success_callback_detached() throws AblyException { - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; try { ClientOptions opts = createOptions(testVars.keys[0].keyStr); - ably = new AblyRealtime(opts); + ably = RealtimeClientFactory.create(opts); /* wait until connected */ (new ConnectionWaiter(ably.connection)).waitFor(ConnectionState.connected); @@ -1470,11 +1471,11 @@ public void detach_success_callback_detached() throws AblyException { @Ignore("FIXME: fix exception") @Test public void transient_publish_connected() throws AblyException { - AblyRealtime pubAbly = null, subAbly = null; + PubSubRealtimeClient pubAbly = null, subAbly = null; String channelName = "transient_publish_connected_" + testParams.name; try { ClientOptions opts = createOptions(testVars.keys[0].keyStr); - subAbly = new AblyRealtime(opts); + subAbly = RealtimeClientFactory.create(opts); /* wait until connected */ new ConnectionWaiter(subAbly.connection).waitFor(ConnectionState.connected); @@ -1485,7 +1486,7 @@ public void transient_publish_connected() throws AblyException { Helpers.MessageWaiter messageWaiter = new Helpers.MessageWaiter(subChannel); new ChannelWaiter(subChannel).waitFor(ChannelState.attached); - pubAbly = new AblyRealtime(opts); + pubAbly = RealtimeClientFactory.create(opts); new ConnectionWaiter(pubAbly.connection).waitFor(ConnectionState.connected); Helpers.CompletionWaiter completionWaiter = new Helpers.CompletionWaiter(); final Channel pubChannel = pubAbly.channels.get(channelName); @@ -1520,11 +1521,11 @@ public void transient_publish_connected() throws AblyException { @Ignore("FIXME: fix exception") @Test public void transient_publish_connecting() throws AblyException { - AblyRealtime pubAbly = null, subAbly = null; + PubSubRealtimeClient pubAbly = null, subAbly = null; String channelName = "transient_publish_connecting_" + testParams.name; try { ClientOptions opts = createOptions(testVars.keys[0].keyStr); - subAbly = new AblyRealtime(opts); + subAbly = RealtimeClientFactory.create(opts); /* wait until connected */ new ConnectionWaiter(subAbly.connection).waitFor(ConnectionState.connected); @@ -1536,7 +1537,7 @@ public void transient_publish_connecting() throws AblyException { Helpers.MessageWaiter messageWaiter = new Helpers.MessageWaiter(subChannel); channelWaiter.waitFor(ChannelState.attached); - pubAbly = new AblyRealtime(opts); + pubAbly = RealtimeClientFactory.create(opts); final Channel pubChannel = pubAbly.channels.get(channelName); Helpers.CompletionWaiter completionWaiter = new Helpers.CompletionWaiter(); pubChannel.publish("Lorem", "Ipsum!", completionWaiter); @@ -1569,11 +1570,11 @@ public void transient_publish_connecting() throws AblyException { */ @Test public void transient_publish_connection_failed() { - AblyRealtime pubAbly = null; + PubSubRealtimeClient pubAbly = null; String channelName = "transient_publish_connection_failed_" + testParams.name; try { ClientOptions opts = createOptions("not:a.key"); - pubAbly = new AblyRealtime(opts); + pubAbly = RealtimeClientFactory.create(opts); new ConnectionWaiter(pubAbly.connection).waitFor(ConnectionState.failed); assertEquals("Verify failed state reached", pubAbly.connection.state, ConnectionState.failed); @@ -1604,11 +1605,11 @@ public void transient_publish_connection_failed() { */ @Test public void transient_publish_channel_failed() { - AblyRealtime pubAbly = null; + PubSubRealtimeClient pubAbly = null; String channelName = "transient_publish_channel_failed_" + testParams.name; try { ClientOptions opts = createOptions(testVars.keys[1].keyStr); - pubAbly = new AblyRealtime(opts); + pubAbly = RealtimeClientFactory.create(opts); new ConnectionWaiter(pubAbly.connection).waitFor(ConnectionState.connected); assertEquals("Verify connected state reached", pubAbly.connection.state, ConnectionState.connected); @@ -1645,10 +1646,10 @@ public void transient_publish_channel_failed() { */ @Test public void attach_implicit_subscribe_fail() throws AblyException { - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; try { ClientOptions opts = createOptions(testVars.keys[1].keyStr); - ably = new AblyRealtime(opts); + ably = RealtimeClientFactory.create(opts); /* wait until connected */ new ConnectionWaiter(ably.connection).waitFor(ConnectionState.connected); @@ -1670,10 +1671,10 @@ public void attach_implicit_subscribe_fail() throws AblyException { @Test public void ensure_detach_with_error_does_not_move_to_failed() { - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; try { ClientOptions opts = createOptions(testVars.keys[0].keyStr); - ably = new AblyRealtime(opts); + ably = RealtimeClientFactory.create(opts); /* wait until connected */ (new ConnectionWaiter(ably.connection)).waitFor(ConnectionState.connected); @@ -1704,11 +1705,11 @@ public void ensure_detach_with_error_does_not_move_to_failed() { @Test public void channel_state_on_connection_suspended() { - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; try { ClientOptions opts = createOptions(testVars.keys[0].keyStr); - ably = new AblyRealtime(opts); + ably = RealtimeClientFactory.create(opts); /* wait until connected */ (new ConnectionWaiter(ably.connection)).waitFor(ConnectionState.connected); @@ -1758,7 +1759,7 @@ public void channel_state_on_connection_suspended() { */ @Test public void channel_server_initiated_attached() throws AblyException { - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; long oldRealtimeTimeout = Defaults.realtimeRequestTimeout; final String channelName = "channel_server_initiated_attach_detach"; @@ -1769,7 +1770,7 @@ public void channel_server_initiated_attached() throws AblyException { Defaults.realtimeRequestTimeout = 1000; opts.channelRetryTimeout = 1000; - ably = new AblyRealtime(opts); + ably = RealtimeClientFactory.create(opts); new ConnectionWaiter(ably.connection).waitFor(ConnectionState.connected); Channel channel = ably.channels.get(channelName); @@ -1807,7 +1808,7 @@ public void channel_server_initiated_attached() throws AblyException { */ @Test public void server_initiated_detach_for_attached_channel() throws AblyException { - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; long oldRealtimeTimeout = Defaults.realtimeRequestTimeout; final String channelName = "channel_server_initiated_detach_for_attached_channel"; @@ -1818,7 +1819,7 @@ public void server_initiated_detach_for_attached_channel() throws AblyException Defaults.realtimeRequestTimeout = 1000; opts.channelRetryTimeout = 1000; - ably = new AblyRealtime(opts); + ably = RealtimeClientFactory.create(opts); new ConnectionWaiter(ably.connection).waitFor(ConnectionState.connected); Channel channel = ably.channels.get(channelName); @@ -1865,7 +1866,7 @@ public void server_initiated_detach_for_attached_channel() throws AblyException */ @Test public void server_initiated_detach_for_suspended_channel() throws AblyException { - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; long oldRealtimeTimeout = Defaults.realtimeRequestTimeout; final String channelName = "channel_server_initiated_detach_for_suspended_channel"; @@ -1876,7 +1877,7 @@ public void server_initiated_detach_for_suspended_channel() throws AblyException Defaults.realtimeRequestTimeout = 1000; opts.channelRetryTimeout = 1000; - ably = new AblyRealtime(opts); + ably = RealtimeClientFactory.create(opts); new ConnectionWaiter(ably.connection).waitFor(ConnectionState.connected); Channel channel = ably.channels.get(channelName); @@ -1927,11 +1928,11 @@ public void server_initiated_detach_for_suspended_channel() throws AblyException */ @Test public void channel_valid_resume_reattach_channels() throws AblyException { - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; try { ClientOptions opts = createOptions(testVars.keys[0].keyStr); - ably = new AblyRealtime(opts); + ably = RealtimeClientFactory.create(opts); ConnectionWaiter connectionWaiter = new ConnectionWaiter(ably.connection); ably.connect(); connectionWaiter.waitFor(ConnectionState.connected); @@ -2000,13 +2001,13 @@ public void channel_valid_resume_reattach_channels() throws AblyException { */ @Test public void channel_invalid_resume_reattach_channels() throws AblyException { - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; final String attachedChannelName = "channel_resume_lost_continuity_attached"; final String suspendedChannelName = "channel_resume_lost_continuity_suspended"; try { ClientOptions opts = createOptions(testVars.keys[0].keyStr); - ably = new AblyRealtime(opts); + ably = RealtimeClientFactory.create(opts); ConnectionWaiter connectionWaiter = new ConnectionWaiter(ably.connection); ably.connect(); connectionWaiter.waitFor(ConnectionState.connected); @@ -2046,7 +2047,7 @@ public void channel_invalid_resume_reattach_channels() throws AblyException { assertSame(resumeError, ably.connection.connectionManager.getStateErrorInfo()); assertNotEquals("A new connection was created", originalConnectionId, ably.connection.id); - AblyRealtime finalAbly = ably; + PubSubRealtimeClient finalAbly = ably; Exception conditionError = new Helpers.ConditionalWaiter(). wait(() -> finalAbly.connection.connectionManager.msgSerial == 0, 10000); assertNull(conditionError); @@ -2089,7 +2090,7 @@ public void channel_invalid_resume_reattach_channels() throws AblyException { */ @Test public void channel_attach_retry_failed() { - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; String channelName = "channel_attach_retry_failed_" + testParams.name; long oldRealtimeTimeout = Defaults.realtimeRequestTimeout; try { @@ -2105,7 +2106,7 @@ public void channel_attach_retry_failed() { /* Reduce timeout for test to run faster */ Defaults.realtimeRequestTimeout = 1000; - ably = new AblyRealtime(opts); + ably = RealtimeClientFactory.create(opts); ConnectionWaiter connectionWaiter = new ConnectionWaiter(ably.connection); connectionWaiter.waitFor(ConnectionState.connected); @@ -2205,7 +2206,7 @@ public void onError(ErrorInfo reason) { */ @Test public void channel_reattach_failed_timeout() { - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; final String channelName = "channel_reattach_failed_timeout_" + testParams.name; long oldRealtimeTimeout = Defaults.realtimeRequestTimeout; try { @@ -2221,7 +2222,7 @@ public void channel_reattach_failed_timeout() { /* Reduce timeout for test to run faster */ Defaults.realtimeRequestTimeout = 1000; - ably = new AblyRealtime(opts); + ably = RealtimeClientFactory.create(opts); ConnectionWaiter connectionWaiter = new ConnectionWaiter(ably.connection); connectionWaiter.waitFor(ConnectionState.connected); @@ -2270,7 +2271,7 @@ public void channel_reattach_failed_timeout() { */ @Test public void channel_reattach_failed_error() { - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; final String channelName = "channel_reattach_failed_error_" + testParams.name; final int errorCode = 12345; long oldRealtimeTimeout = Defaults.realtimeRequestTimeout; @@ -2287,7 +2288,7 @@ public void channel_reattach_failed_error() { /* Reduce timeout for test to run faster */ Defaults.realtimeRequestTimeout = 5000; - ably = new AblyRealtime(opts); + ably = RealtimeClientFactory.create(opts); ConnectionWaiter connectionWaiter = new ConnectionWaiter(ably.connection); connectionWaiter.waitFor(ConnectionState.connected); @@ -2349,7 +2350,7 @@ public void attach_exception_listener_called() { /* init Ably */ ClientOptions opts = createOptions(testVars.keys[0].keyStr); - AblyRealtime ably = new AblyRealtime(opts); + PubSubRealtimeClient ably = RealtimeClientFactory.create(opts); /* wait until connected */ (new ConnectionWaiter(ably.connection)).waitFor(ConnectionState.connected); @@ -2403,7 +2404,7 @@ public void onError(ErrorInfo reason) { @Test public void no_messages_when_channel_state_not_attached() { - AblyRealtime senderReceiver = null; + PubSubRealtimeClient senderReceiver = null; final String testMessage1 = "{ foo: \"bar\", count: 1, status: \"active\" }"; final String testMessage2 = "{ foo: \"bar\", count: 2, status: \"active\" }"; @@ -2412,7 +2413,7 @@ public void no_messages_when_channel_state_not_attached() { DebugOptions common_opts = createOptions(testVars.keys[0].keyStr); common_opts.protocolListener = new DetachingProtocolListener(); - senderReceiver = new AblyRealtime(common_opts); + senderReceiver = RealtimeClientFactory.create(common_opts); Channel sender_channel = senderReceiver.channels.get(testName); ((DetachingProtocolListener)common_opts.protocolListener).theChannel = sender_channel; @@ -2447,7 +2448,7 @@ public void no_messages_when_channel_state_not_attached() { */ @Test public void detach_message_to_released_channel_is_dropped() throws AblyException { - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; long oldRealtimeTimeout = Defaults.realtimeRequestTimeout; final String channelName = "detach_message_to_released_channel_is_dropped"; @@ -2460,7 +2461,7 @@ public void detach_message_to_released_channel_is_dropped() throws AblyException Defaults.realtimeRequestTimeout = 1000; opts.channelRetryTimeout = 1000; - ably = new AblyRealtime(opts); + ably = RealtimeClientFactory.create(opts); Channel channel = ably.channels.get(channelName); channel.attach(); (new ChannelWaiter(channel)).waitFor(ChannelState.attached); @@ -2488,7 +2489,7 @@ public void detach_message_to_released_channel_is_dropped() throws AblyException @Test public void connect_on_closed_client_should_reinitialize_channels() throws AblyException { ClientOptions opts = createOptions(testVars.keys[0].keyStr); - try (AblyRealtime ably = new AblyRealtime(opts)) { + try (PubSubRealtimeClient ably = RealtimeClientFactory.create(opts)) { /* wait until connected */ new ConnectionWaiter(ably.connection).waitFor(ConnectionState.connected); @@ -2532,7 +2533,7 @@ public void connect_on_closed_client_should_reinitialize_channels() throws AblyE @Test public void connect_on_closing_client_should_reinitialize_channels() throws AblyException { ClientOptions opts = createOptions(testVars.keys[0].keyStr); - try (AblyRealtime ably = new AblyRealtime(opts)) { + try (PubSubRealtimeClient ably = RealtimeClientFactory.create(opts)) { /* wait until connected */ (new ConnectionWaiter(ably.connection)).waitFor(ConnectionState.connected); @@ -2575,7 +2576,7 @@ public void connect_on_closing_client_should_reinitialize_channels() throws Ably @Test public void release_should_not_prevent_graceful_test_end() throws Exception { ClientOptions opts = createOptions(testVars.keys[0].keyStr); - try (AblyRealtime ably = new AblyRealtime(opts)) { + try (PubSubRealtimeClient ably = RealtimeClientFactory.create(opts)) { ably.channels.get("channel_should_be_released"); ably.channels.release("channel_should_be_released"); } @@ -2616,7 +2617,7 @@ private String stringStackTrace(Thread thread) { @Test public void connect_should_not_rewrite_immediate_attach() throws AblyException { ClientOptions opts = createOptions(testVars.keys[0].keyStr); - try (AblyRealtime ably = new AblyRealtime(opts)) { + try (PubSubRealtimeClient ably = RealtimeClientFactory.create(opts)) { ably.close(); new ConnectionWaiter(ably.connection).waitFor(ConnectionState.closed); assertEquals("Verify closed state reached", ConnectionState.closed, ably.connection.state); @@ -2632,7 +2633,7 @@ public void connect_should_not_rewrite_immediate_attach() throws AblyException { @Test public void channel_get_objects_throws_exception() throws AblyException { ClientOptions opts = createOptions(testVars.keys[0].keyStr); - try (AblyRealtime ably = new AblyRealtime(opts)) { + try (PubSubRealtimeClient ably = RealtimeClientFactory.create(opts)) { /* wait until connected */ new ConnectionWaiter(ably.connection).waitFor(ConnectionState.connected); @@ -2665,7 +2666,7 @@ public void channel_get_objects_throws_exception() throws AblyException { @Test public void channel_state_is_attaching_on_reconnected() throws AblyException { ClientOptions opts = createOptions(testVars.keys[0].keyStr); - AblyRealtime ably = new AblyRealtime(opts); + PubSubRealtimeClient ably = RealtimeClientFactory.create(opts); ConnectionWaiter connectionWaiter = new ConnectionWaiter(ably.connection); /* attach channel and wait for it to be fully attached */ diff --git a/lib/src/test/java/io/ably/lib/test/realtime/RealtimeConnectFailTest.java b/lib/src/test/java/io/ably/pubsub/test/realtime/RealtimeConnectFailTest.java similarity index 87% rename from lib/src/test/java/io/ably/lib/test/realtime/RealtimeConnectFailTest.java rename to lib/src/test/java/io/ably/pubsub/test/realtime/RealtimeConnectFailTest.java index 7d6ea43f3..571110865 100644 --- a/lib/src/test/java/io/ably/lib/test/realtime/RealtimeConnectFailTest.java +++ b/lib/src/test/java/io/ably/pubsub/test/realtime/RealtimeConnectFailTest.java @@ -1,28 +1,30 @@ -package io.ably.lib.test.realtime; - -import io.ably.lib.debug.DebugOptions; -import io.ably.lib.realtime.AblyRealtime; -import io.ably.lib.realtime.Channel; -import io.ably.lib.realtime.ChannelState; -import io.ably.lib.realtime.ConnectionEvent; -import io.ably.lib.realtime.ConnectionState; -import io.ably.lib.realtime.ConnectionStateListener; -import io.ably.lib.rest.AblyRest; -import io.ably.lib.rest.Auth; -import io.ably.lib.rest.Auth.TokenCallback; -import io.ably.lib.rest.Auth.TokenDetails; -import io.ably.lib.rest.Auth.TokenParams; -import io.ably.lib.test.common.Helpers; -import io.ably.lib.test.common.Helpers.ConnectionWaiter; -import io.ably.lib.test.common.ParameterizedTest; -import io.ably.lib.test.util.MockWebsocketFactory; -import io.ably.lib.transport.Defaults; -import io.ably.lib.types.AblyException; -import io.ably.lib.types.Callback; -import io.ably.lib.types.ClientOptions; -import io.ably.lib.types.ErrorInfo; -import io.ably.lib.types.ProtocolMessage; -import io.ably.lib.types.PublishResult; +package io.ably.pubsub.test.realtime; + +import io.ably.pubsub.debug.DebugOptions; +import io.ably.pubsub.realtime.PubSubRealtimeClient; +import io.ably.pubsub.realtime.RealtimeClientFactory; +import io.ably.pubsub.realtime.Channel; +import io.ably.pubsub.realtime.ChannelState; +import io.ably.pubsub.realtime.ConnectionEvent; +import io.ably.pubsub.realtime.ConnectionState; +import io.ably.pubsub.realtime.ConnectionStateListener; +import io.ably.pubsub.http.HttpClientFactory; +import io.ably.pubsub.http.PubSubHttpClient; +import io.ably.pubsub.http.Auth; +import io.ably.pubsub.http.Auth.TokenCallback; +import io.ably.pubsub.http.Auth.TokenDetails; +import io.ably.pubsub.http.Auth.TokenParams; +import io.ably.pubsub.test.common.Helpers; +import io.ably.pubsub.test.common.Helpers.ConnectionWaiter; +import io.ably.pubsub.test.common.ParameterizedTest; +import io.ably.pubsub.test.util.MockWebsocketFactory; +import io.ably.pubsub.transport.Defaults; +import io.ably.pubsub.types.AblyException; +import io.ably.pubsub.types.Callback; +import io.ably.pubsub.types.ClientOptions; +import io.ably.pubsub.types.ErrorInfo; +import io.ably.pubsub.types.ProtocolMessage; +import io.ably.pubsub.types.PublishResult; import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; @@ -35,7 +37,7 @@ import java.util.List; import java.util.Locale; -import static io.ably.lib.test.common.Helpers.assertTimeoutBetween; +import static io.ably.pubsub.test.common.Helpers.assertTimeoutBetween; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; @@ -54,10 +56,10 @@ public class RealtimeConnectFailTest extends ParameterizedTest { */ @Test public void connect_fail_notfound_error() throws AblyException { - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; try { ClientOptions opts = createOptions("not_an_app.invalid_key_id:invalid_key_value"); - ably = new AblyRealtime(opts); + ably = RealtimeClientFactory.create(opts); ConnectionWaiter connectionWaiter = new ConnectionWaiter(ably.connection); ErrorInfo fail = connectionWaiter.waitFor(ConnectionState.failed); @@ -74,11 +76,11 @@ public void connect_fail_notfound_error() throws AblyException { */ @Test public void connect_fail_authorized_error() throws AblyException { - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; try { String keyId = testVars.keys[0].keyName.split("\\.")[1]; ClientOptions opts = createOptions(testVars.appId + "." + keyId + ":invalid_key_value"); - ably = new AblyRealtime(opts); + ably = RealtimeClientFactory.create(opts); ConnectionWaiter connectionWaiter = new ConnectionWaiter(ably.connection); ErrorInfo fail = connectionWaiter.waitFor(ConnectionState.failed); @@ -96,9 +98,8 @@ public void connect_fail_authorized_error() throws AblyException { @Test public void connect_fail_disconnected() throws AblyException { ClientOptions opts = createOptions(testVars.keys[0].keyStr); - opts.realtimeHost = "non.existent.host"; - opts.environment = null; - AblyRealtime ably = new AblyRealtime(opts); + opts.endpoint = "non.existent.host"; + PubSubRealtimeClient ably = RealtimeClientFactory.create(opts); ConnectionWaiter connectionWaiter = new ConnectionWaiter(ably.connection); connectionWaiter.waitFor(ConnectionState.disconnected); @@ -116,9 +117,8 @@ public void connect_fail_disconnected() throws AblyException { public void connect_fail_suspended() { try { ClientOptions opts = createOptions(testVars.keys[0].keyStr); - opts.realtimeHost = "non.existent.host"; - opts.environment = null; - AblyRealtime ably = new AblyRealtime(opts); + opts.endpoint = "non.existent.host"; + PubSubRealtimeClient ably = RealtimeClientFactory.create(opts); ConnectionWaiter connectionWaiter = new ConnectionWaiter(ably.connection); connectionWaiter.waitFor(ConnectionState.suspended); @@ -145,7 +145,7 @@ public void connect_after_suspend_should_clean_msg_serial() throws AblyException ClientOptions opts = createOptions(testVars.keys[0].keyStr); opts.disconnectedRetryTimeout = Integer.MAX_VALUE; opts.suspendedRetryTimeout = Integer.MAX_VALUE; - try (AblyRealtime ably = new AblyRealtime(opts)) { + try (PubSubRealtimeClient ably = RealtimeClientFactory.create(opts)) { ConnectionWaiter waiter = new ConnectionWaiter(ably.connection); waiter.waitFor(ConnectionState.connecting); ably.connection.connectionManager.requestState(ConnectionState.suspended); @@ -168,9 +168,8 @@ public void connect_after_suspend_should_clean_msg_serial() throws AblyException public void connect_while_disconnected() { try { ClientOptions opts = createOptions(testVars.keys[0].keyStr); - opts.realtimeHost = "non.existent.host"; - opts.environment = null; - AblyRealtime ably = new AblyRealtime(opts); + opts.endpoint = "non.existent.host"; + PubSubRealtimeClient ably = RealtimeClientFactory.create(opts); ConnectionWaiter connectionWaiter = new ConnectionWaiter(ably.connection); connectionWaiter.waitFor(ConnectionState.disconnected); @@ -198,12 +197,12 @@ public void connect_while_disconnected() { public void connect_token_expire_disconnected() { try { final ClientOptions optsForToken = createOptions(testVars.keys[0].keyStr); - final AblyRest ablyForToken = new AblyRest(optsForToken); - Auth.AuthOptions restAuthOptions = new Auth.AuthOptions() {{ + final PubSubHttpClient ablyForToken = HttpClientFactory.create(optsForToken); + Auth.AuthOptions httpAuthOptions = new Auth.AuthOptions() {{ key = optsForToken.key; queryTime = true; }}; - TokenDetails tokenDetails = ablyForToken.auth.requestToken(new TokenParams() {{ ttl = 8000L; }}, restAuthOptions); + TokenDetails tokenDetails = ablyForToken.auth.requestToken(new TokenParams() {{ ttl = 8000L; }}, httpAuthOptions); assertNotNull("Expected token value", tokenDetails.token); /* implement callback, using Ably instance with key */ @@ -223,7 +222,7 @@ public Object getTokenRequest(TokenParams params) throws AblyException { ClientOptions opts = createOptions(); opts.tokenDetails = tokenDetails; opts.authCallback = authCallback; - AblyRealtime ably = new AblyRealtime(opts); + PubSubRealtimeClient ably = RealtimeClientFactory.create(opts); ably.connection.on(new ConnectionStateListener() { @Override @@ -266,7 +265,7 @@ public void onConnectionStateChanged(ConnectionStateChange state) { public void connect_token_expire_inplace_reauth() { try { ClientOptions optsForToken = createOptions(testVars.keys[0].keyStr); - final AblyRest ablyForToken = new AblyRest(optsForToken); + final PubSubHttpClient ablyForToken = HttpClientFactory.create(optsForToken); /* Server will send reauth message 30 seconds before token expiration time i.e. in 4 seconds */ TokenDetails tokenDetails = ablyForToken.auth.requestToken(new TokenParams() {{ ttl = 34000L; }}, null); assertNotNull("Expected token value", tokenDetails.token); @@ -290,7 +289,7 @@ public Object getTokenRequest(TokenParams params) throws AblyException { return ablyForToken.auth.requestToken(params, null); } }; - AblyRealtime ably = new AblyRealtime(opts); + PubSubRealtimeClient ably = RealtimeClientFactory.create(opts); /* Test UPDATE event delivery */ ably.connection.on(ConnectionEvent.update, new ConnectionStateListener() { @@ -334,11 +333,11 @@ public void onConnectionStateChanged(ConnectionStateChange state) { @Ignore("FIXME: fix exception") @Test public void connect_invalid_recover_fail() { - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; try { ClientOptions opts = createOptions(testVars.keys[0].keyStr); opts.recover = "not_a_valid_connection_id:99"; - ably = new AblyRealtime(opts); + ably = RealtimeClientFactory.create(opts); ConnectionWaiter connectionWaiter = new ConnectionWaiter(ably.connection); ErrorInfo fail = connectionWaiter.waitFor(ConnectionState.failed); assertEquals("Verify failed state is reached", ConnectionState.failed, ably.connection.state); @@ -358,13 +357,13 @@ public void connect_invalid_recover_fail() { */ @Test public void connect_unknown_recover_fail() { - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; try { ClientOptions opts = createOptions(testVars.keys[0].keyStr); String recoveryKey = "{\"connectionKey\":\"0123456789abcdef-99\",\"msgSerial\":5,\"channelSerials\":{\"channel1\":\"98\",\"channel2\":\"32\",\"channel3\":\"09\"}}"; opts.recover = recoveryKey; - ably = new AblyRealtime(opts); + ably = RealtimeClientFactory.create(opts); ConnectionWaiter connectionWaiter = new ConnectionWaiter(ably.connection); ErrorInfo connectedError = connectionWaiter.waitFor(ConnectionState.connected); assertEquals("Verify connected state is reached", ConnectionState.connected, ably.connection.state); @@ -386,10 +385,10 @@ public void connect_unknown_recover_fail() { @Test public void connect_test_queued_messages_on_failure() { - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; try { ClientOptions opts = createOptions(testVars.keys[0].keyStr); - ably = new AblyRealtime(opts); + ably = RealtimeClientFactory.create(opts); final int[] numberOfErrors = new int[]{0}; // assume we are in connecting state now @@ -440,8 +439,8 @@ public void connect_reauth_failure_state_flow_test() { try { ClientOptions opts = createOptions(testVars.keys[0].keyStr); - AblyRest ablyRest = new AblyRest(opts); - final TokenDetails tokenDetails = ablyRest.auth.requestToken(new TokenParams() {{ ttl = 2000L; }}, null); + PubSubHttpClient pubSubHttpClient = HttpClientFactory.create(opts); + final TokenDetails tokenDetails = pubSubHttpClient.auth.requestToken(new TokenParams() {{ ttl = 2000L; }}, null); assertNotNull("Expected token value", tokenDetails.token); final ArrayList stateHistory = new ArrayList<>(); @@ -455,9 +454,9 @@ public Object getTokenRequest(TokenParams params) throws AblyException { } }; optsForRealtime.tokenDetails = tokenDetails; - final AblyRealtime ablyRealtime = new AblyRealtime(optsForRealtime); + final PubSubRealtimeClient realtimeClient = RealtimeClientFactory.create(optsForRealtime); - (new ConnectionWaiter(ablyRealtime.connection)).waitFor(ConnectionState.connected); + (new ConnectionWaiter(realtimeClient.connection)).waitFor(ConnectionState.connected); final List correctHistory = Arrays.asList( ConnectionState.disconnected, ConnectionState.connecting, @@ -466,7 +465,7 @@ public Object getTokenRequest(TokenParams params) throws AblyException { ConnectionState.disconnected ); final int maxDisconnections = 3; - ablyRealtime.connection.on(new ConnectionStateListener() { + realtimeClient.connection.on(new ConnectionStateListener() { int disconnections = 0; @Override public void onConnectionStateChanged(ConnectionStateChange state) { @@ -476,14 +475,14 @@ public void onConnectionStateChanged(ConnectionStateChange state) { disconnections++; if (disconnections == maxDisconnections) { assertEquals(correctHistory, stateHistory); - ablyRealtime.close(); + realtimeClient.close(); } } } } }); - ConnectionWaiter connectionWaiter = new ConnectionWaiter(ablyRealtime.connection); + ConnectionWaiter connectionWaiter = new ConnectionWaiter(realtimeClient.connection); connectionWaiter.waitFor(ConnectionState.closed); } catch (AblyException e) { e.printStackTrace(); @@ -496,8 +495,8 @@ public void onConnectionStateChanged(ConnectionStateChange state) { */ @Test public void connect_auth_failure_and_suspend_test() { - AblyRealtime ablyRealtime = null; - AblyRest ablyRest = null; + PubSubRealtimeClient realtimeClient = null; + PubSubHttpClient pubSubHttpClient = null; try { /* Make test faster */ @@ -507,8 +506,8 @@ public void connect_auth_failure_and_suspend_test() { ClientOptions opts = createOptions(testVars.keys[0].keyStr); opts.disconnectedRetryTimeout = 1000; - ablyRest = new AblyRest(opts); - final TokenDetails tokenDetails = ablyRest.auth.requestToken(new TokenParams() {{ ttl = 5000L; }}, null); + pubSubHttpClient = HttpClientFactory.create(opts); + final TokenDetails tokenDetails = pubSubHttpClient.auth.requestToken(new TokenParams() {{ ttl = 5000L; }}, null); assertNotNull("Expected token value", tokenDetails.token); ClientOptions optsForRealtime = createOptions(); @@ -521,9 +520,9 @@ public Object getTokenRequest(TokenParams params) throws AblyException { throw AblyException.fromErrorInfo(new ErrorInfo("Auth failure", 90000)); } }; - ablyRealtime = new AblyRealtime(optsForRealtime); + realtimeClient = RealtimeClientFactory.create(optsForRealtime); - ablyRealtime.connection.on(new ConnectionStateListener() { + realtimeClient.connection.on(new ConnectionStateListener() { @Override public void onConnectionStateChanged(ConnectionStateChange state) { System.out.format(Locale.ROOT, "New state: %s\n", state.current); @@ -542,13 +541,13 @@ public void onConnectionStateChanged(ConnectionStateChange state) { } } - assertEquals("Verify suspended state", ablyRealtime.connection.state, ConnectionState.suspended); + assertEquals("Verify suspended state", realtimeClient.connection.state, ConnectionState.suspended); } catch (AblyException e) { e.printStackTrace(); fail("init0: Unexpected exception instantiating library"); } finally { - if (ablyRealtime != null) - ablyRealtime.close(); + if (realtimeClient != null) + realtimeClient.close(); } } @@ -559,13 +558,12 @@ public void onConnectionStateChanged(ConnectionStateChange state) { @Test public void disconnect_retry_connection_timeout_jitter() { - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; try { ClientOptions opts = createOptions(testVars.keys[0].keyStr); - opts.realtimeHost = "non.existent.host"; - opts.environment = null; + opts.endpoint = "non.existent.host"; opts.disconnectedRetryTimeout = 5000; // Disconnected retry timeout set to 5 seconds. - ably = new AblyRealtime(opts); + ably = RealtimeClientFactory.create(opts); final ArrayList disconnectedRetryTimeouts = new ArrayList<>(); @@ -608,7 +606,7 @@ public void disconnect_retry_connection_timeout_jitter() { */ @Test public void disconnect_retry_channel_timeout_jitter_after_first_detach() { - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; try { DebugOptions opts = new DebugOptions(testVars.keys[0].keyStr); opts.channelRetryTimeout = 5000; // channel retry timeout set to 5 seconds. @@ -617,7 +615,7 @@ public void disconnect_retry_channel_timeout_jitter_after_first_detach() { ((MockWebsocketFactory)opts.transportFactory).allowSend(); fillInOptions(opts); - ably = new AblyRealtime(opts); + ably = RealtimeClientFactory.create(opts); new ConnectionWaiter(ably.connection).waitFor(ConnectionState.connected); /* Block send() */ @@ -674,7 +672,7 @@ public void disconnect_retry_channel_timeout_jitter_after_first_detach() { @Test public void disconnect_retry_channel_timeout_jitter_after_consistent_detach() { - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; try { DebugOptions opts = new DebugOptions(testVars.keys[0].keyStr); opts.channelRetryTimeout = 5000; // channel retry timeout set to 5 seconds., no realtimeRequestTimeout is set. @@ -682,7 +680,7 @@ public void disconnect_retry_channel_timeout_jitter_after_consistent_detach() { ((MockWebsocketFactory)opts.transportFactory).allowSend(); fillInOptions(opts); - ably = new AblyRealtime(opts); + ably = RealtimeClientFactory.create(opts); new ConnectionWaiter(ably.connection).waitFor(ConnectionState.connected); /* Block send() */ diff --git a/lib/src/test/java/io/ably/lib/test/realtime/RealtimeConnectTest.java b/lib/src/test/java/io/ably/pubsub/test/realtime/RealtimeConnectTest.java similarity index 87% rename from lib/src/test/java/io/ably/lib/test/realtime/RealtimeConnectTest.java rename to lib/src/test/java/io/ably/pubsub/test/realtime/RealtimeConnectTest.java index 044d1a979..6efd9c3f7 100644 --- a/lib/src/test/java/io/ably/lib/test/realtime/RealtimeConnectTest.java +++ b/lib/src/test/java/io/ably/pubsub/test/realtime/RealtimeConnectTest.java @@ -1,4 +1,4 @@ -package io.ably.lib.test.realtime; +package io.ably.pubsub.test.realtime; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -6,24 +6,25 @@ import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; -import io.ably.lib.test.common.Helpers; -import io.ably.lib.types.AsyncHttpPaginatedResponse; -import io.ably.lib.types.ErrorInfo; +import io.ably.pubsub.test.common.Helpers; +import io.ably.pubsub.types.AsyncHttpPaginatedResponse; +import io.ably.pubsub.types.ErrorInfo; import org.junit.Ignore; import org.junit.Test; -import io.ably.lib.debug.DebugOptions; -import io.ably.lib.debug.DebugOptions.RawProtocolListener; -import io.ably.lib.realtime.AblyRealtime; -import io.ably.lib.realtime.ConnectionState; -import io.ably.lib.rest.Auth.AuthMethod; -import io.ably.lib.test.common.Helpers.CompletionWaiter; -import io.ably.lib.test.common.Helpers.ConnectionWaiter; -import io.ably.lib.test.common.ParameterizedTest; -import io.ably.lib.types.AblyException; -import io.ably.lib.types.ClientOptions; -import io.ably.lib.types.Param; -import io.ably.lib.types.ProtocolMessage; +import io.ably.pubsub.debug.DebugOptions; +import io.ably.pubsub.debug.DebugOptions.RawProtocolListener; +import io.ably.pubsub.realtime.PubSubRealtimeClient; +import io.ably.pubsub.realtime.RealtimeClientFactory; +import io.ably.pubsub.realtime.ConnectionState; +import io.ably.pubsub.http.Auth.AuthMethod; +import io.ably.pubsub.test.common.Helpers.CompletionWaiter; +import io.ably.pubsub.test.common.Helpers.ConnectionWaiter; +import io.ably.pubsub.test.common.ParameterizedTest; +import io.ably.pubsub.types.AblyException; +import io.ably.pubsub.types.ClientOptions; +import io.ably.pubsub.types.Param; +import io.ably.pubsub.types.ProtocolMessage; import org.junit.rules.Timeout; import java.util.concurrent.atomic.AtomicLong; @@ -41,7 +42,7 @@ public class RealtimeConnectTest extends ParameterizedTest { public void connect() { try { ClientOptions opts = createOptions(testVars.keys[0].keyStr); - AblyRealtime ably = new AblyRealtime(opts); + PubSubRealtimeClient ably = RealtimeClientFactory.create(opts); ConnectionWaiter connectionWaiter = new ConnectionWaiter(ably.connection); connectionWaiter.waitFor(ConnectionState.connected); @@ -66,7 +67,7 @@ public void connect_heartbeat() { try { ClientOptions opts = createOptions(testVars.keys[0].keyStr); CompletionWaiter heartbeatWaiter = new CompletionWaiter(); - AblyRealtime ably = new AblyRealtime(opts); + PubSubRealtimeClient ably = RealtimeClientFactory.create(opts); ConnectionWaiter connectionWaiter = new ConnectionWaiter(ably.connection); connectionWaiter.waitFor(ConnectionState.connected); assertEquals("Verify connected state is reached", ConnectionState.connected, ably.connection.state); @@ -91,7 +92,7 @@ public void connect_heartbeat() { public void connect_after_close() { try { ClientOptions opts = createOptions(testVars.keys[0].keyStr); - AblyRealtime ably = new AblyRealtime(opts); + PubSubRealtimeClient ably = RealtimeClientFactory.create(opts); ConnectionWaiter connectionWaiter = new ConnectionWaiter(ably.connection); connectionWaiter.waitFor(ConnectionState.connected); assertEquals("Verify connected state is reached", ConnectionState.connected, ably.connection.state); @@ -136,11 +137,11 @@ public void connect_after_close() { */ @Test public void connect_useTokenAuth() { - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; try { ClientOptions opts = createOptions(testVars.keys[0].keyStr); opts.useTokenAuth = true; - ably = new AblyRealtime(opts); + ably = RealtimeClientFactory.create(opts); ConnectionWaiter connectionWaiter = new ConnectionWaiter(ably.connection); connectionWaiter.waitFor(ConnectionState.connected); assertEquals("Verify connected state is reached", ConnectionState.connected, ably.connection.state); @@ -177,7 +178,7 @@ public void onRawMessageSend(ProtocolMessage message) {} public void onRawMessageRecv(ProtocolMessage message) {} }; opts.transportParams = new Param[] {new Param("testStringParam", "testStringValue"), new Param("testIntParam", 100), new Param("testBooleanParam", false)}; - AblyRealtime ably = new AblyRealtime(opts); + PubSubRealtimeClient ably = RealtimeClientFactory.create(opts); ConnectionWaiter connectionWaiter = new ConnectionWaiter(ably.connection); connectionWaiter.waitFor(ConnectionState.connected); @@ -199,14 +200,14 @@ public void onRawMessageRecv(ProtocolMessage message) {} } /** - * Initiate a connect using AblyRealtime.connect() + * Initiate a connect using PubSubRealtimeClient.connect() */ @Test public void realtime_connect_proxy() { try { ClientOptions opts = createOptions(testVars.keys[0].keyStr); opts.autoConnect = false; - AblyRealtime ably = new AblyRealtime(opts); + PubSubRealtimeClient ably = RealtimeClientFactory.create(opts); ConnectionWaiter connectionWaiter = new ConnectionWaiter(ably.connection); /* verify no connection happens */ @@ -234,7 +235,7 @@ public void realtime_connect_proxy() { public void close_when_connecting() { try { ClientOptions opts = createOptions(testVars.keys[0].keyStr); - AblyRealtime ably = new AblyRealtime(opts); + PubSubRealtimeClient ably = RealtimeClientFactory.create(opts); ConnectionWaiter connectionWaiter = new ConnectionWaiter(ably.connection); connectionWaiter.waitFor(ConnectionState.connecting); @@ -255,7 +256,7 @@ public void close_when_connecting() { @Test public void reopened_connection_rest_works() throws Exception { - try (AblyRealtime realtimeClient = new AblyRealtime(createOptions(testVars.keys[0].keyStr))) { + try (PubSubRealtimeClient realtimeClient = RealtimeClientFactory.create(createOptions(testVars.keys[0].keyStr))) { realtimeClient.close(); realtimeClient.connect(); diff --git a/lib/src/test/java/io/ably/lib/test/realtime/RealtimeCryptoTest.java b/lib/src/test/java/io/ably/pubsub/test/realtime/RealtimeCryptoTest.java similarity index 90% rename from lib/src/test/java/io/ably/lib/test/realtime/RealtimeCryptoTest.java rename to lib/src/test/java/io/ably/pubsub/test/realtime/RealtimeCryptoTest.java index 2f8acfd05..25ffabff5 100644 --- a/lib/src/test/java/io/ably/lib/test/realtime/RealtimeCryptoTest.java +++ b/lib/src/test/java/io/ably/pubsub/test/realtime/RealtimeCryptoTest.java @@ -1,4 +1,4 @@ -package io.ably.lib.test.realtime; +package io.ably.pubsub.test.realtime; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; @@ -20,22 +20,23 @@ import org.junit.Test; import org.junit.rules.Timeout; -import io.ably.lib.realtime.AblyRealtime; -import io.ably.lib.realtime.Channel; -import io.ably.lib.realtime.ChannelState; -import io.ably.lib.test.common.Helpers.ChannelWaiter; -import io.ably.lib.test.common.Helpers.CompletionSet; -import io.ably.lib.test.common.Helpers.CompletionWaiter; -import io.ably.lib.test.common.Helpers.MessageWaiter; -import io.ably.lib.test.common.ParameterizedTest; -import io.ably.lib.types.AblyException; -import io.ably.lib.types.ChannelOptions; -import io.ably.lib.types.ClientOptions; -import io.ably.lib.types.ErrorInfo; -import io.ably.lib.util.Crypto; -import io.ably.lib.util.Crypto.EncryptingChannelCipher; -import io.ably.lib.util.Crypto.DecryptingChannelCipher; -import io.ably.lib.util.Crypto.CipherParams; +import io.ably.pubsub.realtime.PubSubRealtimeClient; +import io.ably.pubsub.realtime.RealtimeClientFactory; +import io.ably.pubsub.realtime.Channel; +import io.ably.pubsub.realtime.ChannelState; +import io.ably.pubsub.test.common.Helpers.ChannelWaiter; +import io.ably.pubsub.test.common.Helpers.CompletionSet; +import io.ably.pubsub.test.common.Helpers.CompletionWaiter; +import io.ably.pubsub.test.common.Helpers.MessageWaiter; +import io.ably.pubsub.test.common.ParameterizedTest; +import io.ably.pubsub.types.AblyException; +import io.ably.pubsub.types.ChannelOptions; +import io.ably.pubsub.types.ClientOptions; +import io.ably.pubsub.types.ErrorInfo; +import io.ably.pubsub.util.Crypto; +import io.ably.pubsub.util.Crypto.EncryptingChannelCipher; +import io.ably.pubsub.util.Crypto.DecryptingChannelCipher; +import io.ably.pubsub.util.Crypto.CipherParams; public class RealtimeCryptoTest extends ParameterizedTest { @@ -51,10 +52,10 @@ public class RealtimeCryptoTest extends ParameterizedTest { @Test public void single_send() { String channelName = "single_send_" + testParams.name; - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; try { ClientOptions opts = createOptions(testVars.keys[0].keyStr); - ably = new AblyRealtime(opts); + ably = RealtimeClientFactory.create(opts); /* create a channel */ ChannelOptions channelOpts = new ChannelOptions() {{ encrypted = true; }}; @@ -109,10 +110,10 @@ public void single_send() { @Test public void single_send_256() { String channelName = "single_send_256_" + testParams.name; - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; try { ClientOptions opts = createOptions(testVars.keys[0].keyStr); - ably = new AblyRealtime(opts); + ably = RealtimeClientFactory.create(opts); /* create a key */ KeyGenerator keygen = KeyGenerator.getInstance("AES"); @@ -178,10 +179,10 @@ public void single_send_256() { * messages on that channel */ private void _multiple_send(String channelName, int messageCount, long delay) { - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; try { ClientOptions opts = createOptions(testVars.keys[0].keyStr); - ably = new AblyRealtime(opts); + ably = RealtimeClientFactory.create(opts); /* generate and remember message texts */ String[] messageTexts = new String[messageCount]; @@ -265,14 +266,14 @@ public void multiple_send_20_100() { @Test public void single_send_binary_text() { String channelName = "single_send_binary_text_" + testParams.name; - AblyRealtime sender = null; - AblyRealtime receiver = null; + PubSubRealtimeClient sender = null; + PubSubRealtimeClient receiver = null; try { ClientOptions senderOpts = createOptions(testVars.keys[0].keyStr); - sender = new AblyRealtime(senderOpts); + sender = RealtimeClientFactory.create(senderOpts); ClientOptions receiverOpts = createOptions(testVars.keys[0].keyStr); receiverOpts.useBinaryProtocol = !testParams.useBinaryProtocol; - receiver = new AblyRealtime(receiverOpts); + receiver = RealtimeClientFactory.create(receiverOpts); /* create a key */ final CipherParams params = Crypto.getDefaultParams(); @@ -349,13 +350,13 @@ public void single_send_binary_text() { @Ignore("FIXME: fix exception") @Test public void single_send_key_mismatch() { - AblyRealtime sender = null; - AblyRealtime receiver = null; + PubSubRealtimeClient sender = null; + PubSubRealtimeClient receiver = null; try { ClientOptions senderOpts = createOptions(testVars.keys[0].keyStr); - sender = new AblyRealtime(senderOpts); + sender = RealtimeClientFactory.create(senderOpts); ClientOptions receiverOpts = createOptions(testVars.keys[0].keyStr); - receiver = new AblyRealtime(receiverOpts); + receiver = RealtimeClientFactory.create(receiverOpts); /* create a channel */ final ChannelOptions senderChannelOpts = new ChannelOptions() {{ encrypted = true; }}; @@ -423,13 +424,13 @@ public void single_send_key_mismatch() { @Ignore("FIXME: fix exception") @Test public void single_send_unencrypted() { - AblyRealtime sender = null; - AblyRealtime receiver = null; + PubSubRealtimeClient sender = null; + PubSubRealtimeClient receiver = null; try { ClientOptions senderOpts = createOptions(testVars.keys[0].keyStr); - sender = new AblyRealtime(senderOpts); + sender = RealtimeClientFactory.create(senderOpts); ClientOptions receiverOpts = createOptions(testVars.keys[0].keyStr); - receiver = new AblyRealtime(receiverOpts); + receiver = RealtimeClientFactory.create(receiverOpts); /* create a channel */ final Channel senderChannel = sender.channels.get("single_send_unencrypted"); @@ -495,13 +496,13 @@ public void single_send_unencrypted() { @Ignore("FIXME: fix exception") @Test public void single_send_encrypted_unhandled() { - AblyRealtime sender = null; - AblyRealtime receiver = null; + PubSubRealtimeClient sender = null; + PubSubRealtimeClient receiver = null; try { ClientOptions senderOpts = createOptions(testVars.keys[0].keyStr); - sender = new AblyRealtime(senderOpts); + sender = RealtimeClientFactory.create(senderOpts); ClientOptions receiverOpts = createOptions(testVars.keys[0].keyStr); - receiver = new AblyRealtime(receiverOpts); + receiver = RealtimeClientFactory.create(receiverOpts); /* create a channel */ ChannelOptions senderChannelOpts = new ChannelOptions() {{ encrypted = true; }}; @@ -566,14 +567,14 @@ public void single_send_encrypted_unhandled() { @Ignore("FIXME: fix exception") @Test public void set_cipher_params() { - AblyRealtime sender = null; - AblyRealtime receiver = null; + PubSubRealtimeClient sender = null; + PubSubRealtimeClient receiver = null; try { ClientOptions senderOpts = createOptions(testVars.keys[0].keyStr); - sender = new AblyRealtime(senderOpts); + sender = RealtimeClientFactory.create(senderOpts); ClientOptions receiverOpts = createOptions(testVars.keys[0].keyStr); receiverOpts.useBinaryProtocol = !testParams.useBinaryProtocol; - receiver = new AblyRealtime(receiverOpts); + receiver = RealtimeClientFactory.create(receiverOpts); /* create a key */ final CipherParams params1 = Crypto.getDefaultParams(); @@ -674,80 +675,6 @@ public void set_cipher_params() { } } - /** - * Test channel options creation from the cipher key. - * - * This test should be removed when we get rid of the methods - * ChannelOptions.fromCipherKey(...) which are deprecated and have - * been replaced with ChannelOptions.withCipherKey(...). - * @see > requestParameters = null; for (int i = 0; requestParameters == null && i<10; i++) { try { Thread.sleep(100); } catch (InterruptedException e) {} @@ -88,7 +89,7 @@ public void realtime_websocket_param_test() { * Defaults.ABLY_AGENT_PARAM, as ultimately the request param has been derived from those values. */ assertEquals("Verify correct lib version", requestParameters.get("agent"), - Collections.singletonList("ably-java/1.8.2 jre/" + System.getProperty("java.version"))); + Collections.singletonList("ably-pubsub-java/2.0.0 jre/" + System.getProperty("java.version"))); /* Spec RTN2a */ assertEquals("Verify correct format", requestParameters.get("format"), @@ -97,12 +98,12 @@ public void realtime_websocket_param_test() { /* test echo option */ opts = new ClientOptions(key); opts.port = port; - opts.realtimeHost = "localhost"; + opts.endpoint = "localhost"; opts.tls = false; opts.useBinaryProtocol = testParams.useBinaryProtocol; opts.echoMessages = false; server.resetRequestParameters(); - realtime = new AblyRealtime(opts); + realtime = RealtimeClientFactory.create(opts); requestParameters = null; for (int i = 0; requestParameters == null && i<10; i++) { try { Thread.sleep(100); } catch (InterruptedException e) {} @@ -120,7 +121,7 @@ public void realtime_websocket_param_test() { String clientId = "test client id"; opts = new ClientOptions(); opts.port = port; - opts.realtimeHost = "localhost"; + opts.endpoint = "localhost"; opts.tls = false; opts.useBinaryProtocol = testParams.useBinaryProtocol; opts.useTokenAuth = true; @@ -128,7 +129,7 @@ public void realtime_websocket_param_test() { opts.clientId = clientId; server.resetRequestParameters(); - realtime = new AblyRealtime(opts); + realtime = RealtimeClientFactory.create(opts); requestParameters = null; for (int i = 0; requestParameters == null && i<10; i++) { try { Thread.sleep(100); } catch (InterruptedException e) {} diff --git a/lib/src/test/java/io/ably/lib/test/realtime/RealtimeInitTest.java b/lib/src/test/java/io/ably/pubsub/test/realtime/RealtimeInitTest.java similarity index 78% rename from lib/src/test/java/io/ably/lib/test/realtime/RealtimeInitTest.java rename to lib/src/test/java/io/ably/pubsub/test/realtime/RealtimeInitTest.java index 541537bfa..8a30d1682 100644 --- a/lib/src/test/java/io/ably/lib/test/realtime/RealtimeInitTest.java +++ b/lib/src/test/java/io/ably/pubsub/test/realtime/RealtimeInitTest.java @@ -1,4 +1,4 @@ -package io.ably.lib.test.realtime; +package io.ably.pubsub.test.realtime; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -7,13 +7,14 @@ import org.junit.Test; -import io.ably.lib.realtime.AblyRealtime; -import io.ably.lib.test.common.ParameterizedTest; -import io.ably.lib.transport.Defaults; -import io.ably.lib.types.AblyException; -import io.ably.lib.types.ClientOptions; -import io.ably.lib.util.Log; -import io.ably.lib.util.Log.LogHandler; +import io.ably.pubsub.realtime.PubSubRealtimeClient; +import io.ably.pubsub.realtime.RealtimeClientFactory; +import io.ably.pubsub.test.common.ParameterizedTest; +import io.ably.pubsub.transport.Defaults; +import io.ably.pubsub.types.AblyException; +import io.ably.pubsub.types.ClientOptions; +import io.ably.pubsub.util.Log; +import io.ably.pubsub.util.Log.LogHandler; public class RealtimeInitTest extends ParameterizedTest { @@ -22,9 +23,9 @@ public class RealtimeInitTest extends ParameterizedTest { */ @Test public void init_key_string() { - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; try { - ably = new AblyRealtime(testVars.keys[0].keyStr); + ably = RealtimeClientFactory.create(new ClientOptions(testVars.keys[0].keyStr)); } catch (AblyException e) { e.printStackTrace(); fail("init0: Unexpected exception instantiating library"); @@ -38,9 +39,9 @@ public void init_key_string() { */ @Test public void init_key_opts() { - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; try { - ably = new AblyRealtime(new ClientOptions(testVars.keys[0].keyStr)); + ably = RealtimeClientFactory.create(new ClientOptions(testVars.keys[0].keyStr)); } catch (AblyException e) { e.printStackTrace(); fail("init1: Unexpected exception instantiating library"); @@ -54,10 +55,10 @@ public void init_key_opts() { */ @Test public void init_key() { - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; try { ClientOptions opts = new ClientOptions(testVars.keys[0].keyStr); - ably = new AblyRealtime(opts); + ably = RealtimeClientFactory.create(opts); } catch (AblyException e) { e.printStackTrace(); fail("init2: Unexpected exception instantiating library"); @@ -71,12 +72,12 @@ public void init_key() { */ @Test public void init_host() { - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; try { ClientOptions opts = new ClientOptions(testVars.keys[0].keyStr); String hostExpected = "some.other.host"; - opts.restHost = hostExpected; - ably = new AblyRealtime(opts); + opts.endpoint = hostExpected; + ably = RealtimeClientFactory.create(opts); assertEquals("Unexpected host mismatch", hostExpected, ably.httpCore.getPrimaryHost()); } catch (AblyException e) { e.printStackTrace(); @@ -91,12 +92,12 @@ public void init_host() { */ @Test public void init_port() { - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; try { ClientOptions opts = new ClientOptions(testVars.keys[0].keyStr); opts.port = 9998; opts.tlsPort = 9999; - ably = new AblyRealtime(opts); + ably = RealtimeClientFactory.create(opts); assertEquals("Unexpected port mismatch", Defaults.getPort(opts), opts.tlsPort); } catch (AblyException e) { e.printStackTrace(); @@ -111,10 +112,10 @@ public void init_port() { */ @Test public void init_default_secure() { - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; try { ClientOptions opts = new ClientOptions(testVars.keys[0].keyStr); - ably = new AblyRealtime(opts); + ably = RealtimeClientFactory.create(opts); assertEquals("Unexpected port mismatch", Defaults.getPort(opts), Defaults.TLS_PORT); } catch (AblyException e) { e.printStackTrace(); @@ -129,11 +130,11 @@ public void init_default_secure() { */ @Test public void init_insecure() { - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; try { ClientOptions opts = new ClientOptions(testVars.keys[0].keyStr); opts.tls = false; - ably = new AblyRealtime(opts); + ably = RealtimeClientFactory.create(opts); assertEquals("Unexpected scheme mismatch", Defaults.getPort(opts), Defaults.PORT); } catch (AblyException e) { e.printStackTrace(); @@ -149,7 +150,7 @@ public void init_insecure() { private boolean init8_logCalled; @Test public void init_log_handler() { - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; try { ClientOptions opts = new ClientOptions(testVars.keys[0].keyStr); opts.logHandler = new LogHandler() { @@ -160,7 +161,7 @@ public void println(int severity, String tag, String msg, Throwable tr) { } }; opts.logLevel = Log.VERBOSE; - ably = new AblyRealtime(opts); + ably = RealtimeClientFactory.create(opts); assertTrue("Log handler not called", init8_logCalled); } catch (AblyException e) { e.printStackTrace(); @@ -176,7 +177,7 @@ public void println(int severity, String tag, String msg, Throwable tr) { private boolean init9_logCalled; @Test public void init_log_level() { - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; try { ClientOptions opts = new ClientOptions(testVars.keys[0].keyStr); opts.logHandler = new LogHandler() { @@ -187,7 +188,7 @@ public void println(int severity, String tag, String msg, Throwable tr) { } }; opts.logLevel = Log.NONE; - ably = new AblyRealtime(opts); + ably = RealtimeClientFactory.create(opts); assertFalse("Log handler incorrectly called", init9_logCalled); } catch (AblyException e) { e.printStackTrace(); diff --git a/lib/src/test/java/io/ably/lib/test/realtime/RealtimeJWTTest.java b/lib/src/test/java/io/ably/pubsub/test/realtime/RealtimeJWTTest.java similarity index 77% rename from lib/src/test/java/io/ably/lib/test/realtime/RealtimeJWTTest.java rename to lib/src/test/java/io/ably/pubsub/test/realtime/RealtimeJWTTest.java index 1e648aa58..efc2d65b5 100644 --- a/lib/src/test/java/io/ably/lib/test/realtime/RealtimeJWTTest.java +++ b/lib/src/test/java/io/ably/pubsub/test/realtime/RealtimeJWTTest.java @@ -1,30 +1,33 @@ -package io.ably.lib.test.realtime; - -import io.ably.lib.debug.DebugOptions; -import io.ably.lib.debug.DebugOptions.RawProtocolListener; -import io.ably.lib.http.HttpCore; -import io.ably.lib.http.HttpCore.ResponseHandler; -import io.ably.lib.http.HttpHelpers; -import io.ably.lib.realtime.AblyRealtime; -import io.ably.lib.realtime.Channel; -import io.ably.lib.realtime.ChannelState; -import io.ably.lib.realtime.CompletionListener; -import io.ably.lib.realtime.ConnectionEvent; -import io.ably.lib.realtime.ConnectionState; -import io.ably.lib.realtime.ConnectionStateListener; -import io.ably.lib.rest.AblyRest; -import io.ably.lib.rest.Auth.TokenCallback; -import io.ably.lib.rest.Auth.TokenParams; -import io.ably.lib.test.common.Helpers.ChannelWaiter; -import io.ably.lib.test.common.Helpers.ConnectionWaiter; -import io.ably.lib.test.common.ParameterizedTest; -import io.ably.lib.test.common.Setup.Key; -import io.ably.lib.types.AblyException; -import io.ably.lib.types.ClientOptions; -import io.ably.lib.types.ErrorInfo; -import io.ably.lib.types.Message; -import io.ably.lib.types.Param; -import io.ably.lib.types.ProtocolMessage; +package io.ably.pubsub.test.realtime; + +import io.ably.pubsub.debug.DebugOptions; +import io.ably.pubsub.debug.DebugOptions.RawProtocolListener; +import io.ably.pubsub.http.HttpCore; +import io.ably.pubsub.http.HttpCore.ResponseHandler; +import io.ably.pubsub.http.HttpHelpers; +import io.ably.pubsub.realtime.PubSubRealtimeClient; +import io.ably.pubsub.realtime.RealtimeClientFactory; +import io.ably.pubsub.realtime.Channel; +import io.ably.pubsub.realtime.ChannelState; +import io.ably.pubsub.realtime.ConnectionEvent; +import io.ably.pubsub.realtime.ConnectionState; +import io.ably.pubsub.realtime.ConnectionStateListener; +import io.ably.pubsub.http.HttpClientFactory; +import io.ably.pubsub.http.PubSubHttpClient; +import io.ably.pubsub.http.Auth.TokenCallback; +import io.ably.pubsub.http.Auth.TokenParams; +import io.ably.pubsub.test.common.Helpers.ChannelWaiter; +import io.ably.pubsub.test.common.Helpers.ConnectionWaiter; +import io.ably.pubsub.test.common.ParameterizedTest; +import io.ably.pubsub.test.common.Setup.Key; +import io.ably.pubsub.types.AblyException; +import io.ably.pubsub.types.Callback; +import io.ably.pubsub.types.ClientOptions; +import io.ably.pubsub.types.ErrorInfo; +import io.ably.pubsub.types.Message; +import io.ably.pubsub.types.Param; +import io.ably.pubsub.types.PublishResult; +import io.ably.pubsub.types.ProtocolMessage; import org.junit.Ignore; import org.junit.Test; @@ -41,7 +44,7 @@ public class RealtimeJWTTest extends ParameterizedTest { - private AblyRest restJWTRequester; + private PubSubHttpClient httpJWTRequester; private ClientOptions jwtRequesterOptions; private Key key = testVars.keys[0]; private final String clientId = "testJWTClientID"; @@ -65,17 +68,17 @@ public void auth_clientid_match_the_one_requested_in_jwt() { /* create ably realtime with JWT token */ ClientOptions realtimeOptions = buildClientOptions(mergeParams(keys, clientIdParam), null); assertNotNull("Expected token value", realtimeOptions.token); - AblyRealtime ablyRealtime = new AblyRealtime(realtimeOptions); + PubSubRealtimeClient realtimeClient = RealtimeClientFactory.create(realtimeOptions); /* wait for connected state */ - ConnectionWaiter connectionWaiter = new ConnectionWaiter(ablyRealtime.connection); + ConnectionWaiter connectionWaiter = new ConnectionWaiter(realtimeClient.connection); connectionWaiter.waitFor(ConnectionState.connected); - assertEquals("Connected state was NOT reached", ConnectionState.connected, ablyRealtime.connection.state); + assertEquals("Connected state was NOT reached", ConnectionState.connected, realtimeClient.connection.state); /* check expected clientId */ - assertEquals("clientId does NOT match the one requested", clientId, ablyRealtime.auth.clientId); + assertEquals("clientId does NOT match the one requested", clientId, realtimeClient.auth.clientId); - ablyRealtime.close(); + realtimeClient.close(); } catch (AblyException e) { e.printStackTrace(); fail(); @@ -93,23 +96,23 @@ public void auth_jwt_with_subscribe_only_capability() { /* create ably realtime with JWT token that has subscribe-only capabilities */ ClientOptions realtimeOptions = buildClientOptions(keys, susbcribeOnlyCapability); assertNotNull("Expected token value", realtimeOptions.token); - final AblyRealtime ablyRealtime = new AblyRealtime(realtimeOptions); + final PubSubRealtimeClient realtimeClient = RealtimeClientFactory.create(realtimeOptions); /* wait for connected state */ - ConnectionWaiter connectionWaiter = new ConnectionWaiter(ablyRealtime.connection); + ConnectionWaiter connectionWaiter = new ConnectionWaiter(realtimeClient.connection); connectionWaiter.waitFor(ConnectionState.connected); - assertEquals("Connected state was NOT reached", ConnectionState.connected, ablyRealtime.connection.state); + assertEquals("Connected state was NOT reached", ConnectionState.connected, realtimeClient.connection.state); /* attach to channel and verify attached state */ - Channel channel = ablyRealtime.channels.get(channelName); + Channel channel = realtimeClient.channels.get(channelName); channel.attach(); new ChannelWaiter(channel).waitFor(ChannelState.attached); /* publish and verify that it fails */ - channel.publish(messageName, null, new CompletionListener() { + channel.publish(messageName, null, new Callback() { @Override - public void onSuccess() { - ablyRealtime.close(); + public void onSuccess(PublishResult result) { + realtimeClient.close(); fail("It should not succeed"); } @@ -118,7 +121,7 @@ public void onError(ErrorInfo error) { assertEquals("Unexpected status code", 401, error.statusCode); assertEquals("Unexpected error code", 40160, error.code); assertEquals("Unexpected error message", "Unable to perform channel operation (permission denied)", error.message); - ablyRealtime.close(); + realtimeClient.close(); } }); connectionWaiter.waitFor(ConnectionState.closed); @@ -138,30 +141,30 @@ public void auth_jwt_with_publish_capability() { /* create ably realtime with JWT token that has publish capabilities */ ClientOptions realtimeOptions = buildClientOptions(keys, publishCapability); assertNotNull("Expected token value", realtimeOptions.token); - final AblyRealtime ablyRealtime = new AblyRealtime(realtimeOptions); + final PubSubRealtimeClient realtimeClient = RealtimeClientFactory.create(realtimeOptions); /* wait for connected state */ - ConnectionWaiter connectionWaiter = new ConnectionWaiter(ablyRealtime.connection); + ConnectionWaiter connectionWaiter = new ConnectionWaiter(realtimeClient.connection); connectionWaiter.waitFor(ConnectionState.connected); - assertEquals("Connected state was NOT reached", ConnectionState.connected, ablyRealtime.connection.state); + assertEquals("Connected state was NOT reached", ConnectionState.connected, realtimeClient.connection.state); /* attach to channel and verify attached state */ - Channel channel = ablyRealtime.channels.get(channelName); + Channel channel = realtimeClient.channels.get(channelName); channel.attach(); new ChannelWaiter(channel).waitFor(ChannelState.attached); /* publish, verify that it succeeds then close */ final Message message = new Message(messageName, null); - channel.publish(message, new CompletionListener() { + channel.publish(message, new Callback() { @Override - public void onSuccess() { + public void onSuccess(PublishResult result) { System.out.println("Message " + messageName + " published successfully"); - ablyRealtime.close(); + realtimeClient.close(); } @Override public void onError(ErrorInfo reason) { - ablyRealtime.close(); + realtimeClient.close(); fail("Publish should not fail"); } }); @@ -183,15 +186,15 @@ public void auth_jwt_with_token_that_expires() { /* create ably realtime with JWT token that expires in 5 seconds */ ClientOptions realtimeOptions = buildClientOptions(mergeParams(keys, shortTokenTtl), null); assertNotNull("Expected token value", realtimeOptions.token); - final AblyRealtime ablyRealtime = new AblyRealtime(realtimeOptions); + final PubSubRealtimeClient realtimeClient = RealtimeClientFactory.create(realtimeOptions); /* wait for connected state */ - ConnectionWaiter connectionWaiter = new ConnectionWaiter(ablyRealtime.connection); + ConnectionWaiter connectionWaiter = new ConnectionWaiter(realtimeClient.connection); connectionWaiter.waitFor(ConnectionState.connected); - assertEquals("Connected state was NOT reached", ConnectionState.connected, ablyRealtime.connection.state); + assertEquals("Connected state was NOT reached", ConnectionState.connected, realtimeClient.connection.state); /* Verify the expected error reason when disconnected */ - ablyRealtime.connection.once(ConnectionEvent.disconnected, new ConnectionStateListener() { + realtimeClient.connection.once(ConnectionEvent.disconnected, new ConnectionStateListener() { @Override public void onConnectionStateChanged(ConnectionStateChange stateChange) { @@ -219,7 +222,7 @@ public void auth_jwt_with_client_than_reauths_without_disconnecting() { /* create ably realtime with authUrl and params that include a ttl of 35 seconds */ DebugOptions options = new DebugOptions(testVars.keys[0].keyStr); - options.environment = createOptions().environment; + options.endpoint = createOptions().endpoint; options.authUrl = echoServer; options.authParams = mergeParams(keys, mediumTokenTtl); options.protocolListener = new RawProtocolListener() { @@ -236,21 +239,21 @@ public void onRawMessageRecv(ProtocolMessage message) { } } }; - final AblyRealtime ablyRealtime = new AblyRealtime(options); + final PubSubRealtimeClient realtimeClient = RealtimeClientFactory.create(options); /* Once connected for the first time capture the assigned token */ - ablyRealtime.connection.once(ConnectionEvent.connected, new ConnectionStateListener() { + realtimeClient.connection.once(ConnectionEvent.connected, new ConnectionStateListener() { @Override public void onConnectionStateChanged(ConnectionStateChange stateChange) { assertEquals("State is not connected", ConnectionState.connected, stateChange.current); synchronized (tokens) { - tokens[0] = ablyRealtime.auth.getTokenDetails().token; + tokens[0] = realtimeClient.auth.getTokenDetails().token; } } }); /* Fail if the disconnected state is ever reached */ - ablyRealtime.connection.once(ConnectionEvent.disconnected, new ConnectionStateListener() { + realtimeClient.connection.once(ConnectionEvent.disconnected, new ConnectionStateListener() { @Override public void onConnectionStateChanged(ConnectionStateChange stateChange) { fail("Should NOT enter the disconnected state"); @@ -259,20 +262,20 @@ public void onConnectionStateChanged(ConnectionStateChange stateChange) { /* Once receiving the update event check that the token is a new one * and verify the auth protocol message has been received. */ - ablyRealtime.connection.on(ConnectionEvent.update, new ConnectionStateListener() { + realtimeClient.connection.on(ConnectionEvent.update, new ConnectionStateListener() { @Override public void onConnectionStateChanged(ConnectionStateChange state) { - assertNotEquals("Token should not be the same", tokens[0], ablyRealtime.auth.getTokenDetails().token); + assertNotEquals("Token should not be the same", tokens[0], realtimeClient.auth.getTokenDetails().token); assertTrue("Auth protocol message has not been received", authMessages[0]); updateEvents[0] = true; - ablyRealtime.close(); + realtimeClient.close(); } }); /* wait for connected state */ - ConnectionWaiter connectionWaiter = new ConnectionWaiter(ablyRealtime.connection); + ConnectionWaiter connectionWaiter = new ConnectionWaiter(realtimeClient.connection); connectionWaiter.waitFor(ConnectionState.connected); - assertEquals("Connected state was NOT reached", ConnectionState.connected, ablyRealtime.connection.state); + assertEquals("Connected state was NOT reached", ConnectionState.connected, realtimeClient.connection.state); /* wait for closed state */ connectionWaiter.waitFor(ConnectionState.closed); @@ -300,7 +303,7 @@ public void auth_jwt_with_client_than_reauths_without_disconnecting_via_authCall @Override public Object getTokenRequest(TokenParams params) throws AblyException { final String[] resultToken = new String[1]; - AblyRest rest = new AblyRest(createOptions(testVars.keys[0].keyStr)); + PubSubHttpClient rest = HttpClientFactory.create(createOptions(testVars.keys[0].keyStr)); HttpHelpers.getUri(rest.httpCore, echoServer, new Param[]{}, mergeParams(keys, mediumTokenTtl), new ResponseHandler() { @Override public Object handleResponse(HttpCore.Response response, ErrorInfo error) throws AblyException { @@ -322,7 +325,7 @@ public Object handleResponse(HttpCore.Response response, ErrorInfo error) throws /* create ably realtime with authCallback defined above */ DebugOptions options = new DebugOptions(testVars.keys[0].keyStr); - options.environment = createOptions().environment; + options.endpoint = createOptions().endpoint; options.authCallback = authCallback; options.protocolListener = new RawProtocolListener() { @Override @@ -341,49 +344,49 @@ public void onRawMessageRecv(ProtocolMessage message) { } }; - final AblyRealtime ablyRealtime = new AblyRealtime(options); + final PubSubRealtimeClient realtimeClient = RealtimeClientFactory.create(options); /* Once connected for the first time capture the assigned token and * verify the callback has been called once */ - ablyRealtime.connection.once(ConnectionEvent.connected, new ConnectionStateListener() { + realtimeClient.connection.once(ConnectionEvent.connected, new ConnectionStateListener() { @Override public void onConnectionStateChanged(ConnectionStateChange stateChange) { synchronized (tokens) { assertTrue("Callback not called the first time", callbackCalled.get(0)); assertEquals("State is not connected", ConnectionState.connected, stateChange.current); - tokens[0] = ablyRealtime.auth.getTokenDetails().token; + tokens[0] = realtimeClient.auth.getTokenDetails().token; } } }); /* Fail if the disconnected state is ever reached */ - ablyRealtime.connection.once(ConnectionEvent.disconnected, new ConnectionStateListener() { + realtimeClient.connection.once(ConnectionEvent.disconnected, new ConnectionStateListener() { @Override public void onConnectionStateChanged(ConnectionStateChange stateChange) { - ablyRealtime.close(); + realtimeClient.close(); fail("Should NOT enter the disconnected state"); } }); /* Once receiving the update event check that the token is a new one, * verify the auth protocol message has been received and verify the callback has been called twice. */ - ablyRealtime.connection.on(ConnectionEvent.update, new ConnectionStateListener() { + realtimeClient.connection.on(ConnectionEvent.update, new ConnectionStateListener() { @Override public void onConnectionStateChanged(ConnectionStateChange state) { synchronized (tokens) { assertTrue("Callback not called the second time", callbackCalled.get(1)); - assertNotEquals("Token should not be the same", ablyRealtime.auth.getTokenDetails().token, tokens[0]); + assertNotEquals("Token should not be the same", realtimeClient.auth.getTokenDetails().token, tokens[0]); assertTrue("Auth protocol message has not been received", authMessages[0]); updateEvents[0] = true; - ablyRealtime.close(); + realtimeClient.close(); } } }); /* wait for connected state */ - ConnectionWaiter connectionWaiter = new ConnectionWaiter(ablyRealtime.connection); + ConnectionWaiter connectionWaiter = new ConnectionWaiter(realtimeClient.connection); connectionWaiter.waitFor(ConnectionState.connected); - assertEquals("Connected state was NOT reached", ConnectionState.connected, ablyRealtime.connection.state); + assertEquals("Connected state was NOT reached", ConnectionState.connected, realtimeClient.connection.state); /* wait for closed state */ connectionWaiter.waitFor(ConnectionState.closed); @@ -400,7 +403,7 @@ public void onConnectionStateChanged(ConnectionStateChange state) { private ClientOptions buildClientOptions(Param[] params, String capability) { try { final String[] resultToken = new String[1]; - AblyRest rest = new AblyRest(createOptions(testVars.keys[0].keyStr)); + PubSubHttpClient rest = HttpClientFactory.create(createOptions(testVars.keys[0].keyStr)); HttpHelpers.getUri(rest.httpCore, echoServer, null, params, new ResponseHandler() { @Override public Object handleResponse(HttpCore.Response response, ErrorInfo error) throws AblyException { diff --git a/lib/src/test/java/io/ably/lib/test/realtime/RealtimeMessageTest.java b/lib/src/test/java/io/ably/pubsub/test/realtime/RealtimeMessageTest.java similarity index 89% rename from lib/src/test/java/io/ably/lib/test/realtime/RealtimeMessageTest.java rename to lib/src/test/java/io/ably/pubsub/test/realtime/RealtimeMessageTest.java index 550148e3b..20ac5b0cb 100644 --- a/lib/src/test/java/io/ably/lib/test/realtime/RealtimeMessageTest.java +++ b/lib/src/test/java/io/ably/pubsub/test/realtime/RealtimeMessageTest.java @@ -1,4 +1,4 @@ -package io.ably.lib.test.realtime; +package io.ably.pubsub.test.realtime; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; @@ -20,44 +20,46 @@ import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonPrimitive; -import io.ably.lib.test.util.AblyCommonsReader; -import io.ably.lib.types.ChannelOptions; -import io.ably.lib.types.MessageAction; -import io.ably.lib.types.MessageAnnotations; -import io.ably.lib.types.MessageExtras; -import io.ably.lib.types.Param; -import io.ably.lib.types.Summary; -import io.ably.lib.util.Serialisation; +import io.ably.pubsub.test.util.AblyCommonsReader; +import io.ably.pubsub.types.ChannelOptions; +import io.ably.pubsub.types.MessageAction; +import io.ably.pubsub.types.MessageAnnotations; +import io.ably.pubsub.types.MessageExtras; +import io.ably.pubsub.types.Param; +import io.ably.pubsub.types.Summary; +import io.ably.pubsub.util.Serialisation; import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; import org.junit.rules.Timeout; -import io.ably.lib.http.Http; -import io.ably.lib.http.HttpCore; -import io.ably.lib.http.HttpHelpers; -import io.ably.lib.http.HttpScheduler; -import io.ably.lib.http.HttpUtils; -import io.ably.lib.realtime.AblyRealtime; -import io.ably.lib.realtime.Channel; -import io.ably.lib.realtime.ChannelState; -import io.ably.lib.realtime.ConnectionState; -import io.ably.lib.rest.AblyRest; -import io.ably.lib.test.common.Helpers.ChannelWaiter; -import io.ably.lib.test.common.Helpers.CompletionSet; -import io.ably.lib.test.common.Helpers.CompletionWaiter; -import io.ably.lib.test.common.Helpers.ConnectionWaiter; -import io.ably.lib.test.common.Helpers.MessageWaiter; -import io.ably.lib.test.common.Helpers; -import io.ably.lib.test.common.ParameterizedTest; -import io.ably.lib.transport.ConnectionManager; -import io.ably.lib.types.AblyException; -import io.ably.lib.types.Callback; -import io.ably.lib.types.ClientOptions; -import io.ably.lib.types.ErrorInfo; -import io.ably.lib.types.Message; -import io.ably.lib.types.ProtocolMessage; -import io.ably.lib.util.Log; +import io.ably.pubsub.http.HttpRequester; +import io.ably.pubsub.http.HttpCore; +import io.ably.pubsub.http.HttpHelpers; +import io.ably.pubsub.http.HttpScheduler; +import io.ably.pubsub.http.HttpUtils; +import io.ably.pubsub.realtime.PubSubRealtimeClient; +import io.ably.pubsub.realtime.RealtimeClientFactory; +import io.ably.pubsub.realtime.Channel; +import io.ably.pubsub.realtime.ChannelState; +import io.ably.pubsub.realtime.ConnectionState; +import io.ably.pubsub.http.HttpClientFactory; +import io.ably.pubsub.http.PubSubHttpClient; +import io.ably.pubsub.test.common.Helpers.ChannelWaiter; +import io.ably.pubsub.test.common.Helpers.CompletionSet; +import io.ably.pubsub.test.common.Helpers.CompletionWaiter; +import io.ably.pubsub.test.common.Helpers.ConnectionWaiter; +import io.ably.pubsub.test.common.Helpers.MessageWaiter; +import io.ably.pubsub.test.common.Helpers; +import io.ably.pubsub.test.common.ParameterizedTest; +import io.ably.pubsub.transport.ConnectionManager; +import io.ably.pubsub.types.AblyException; +import io.ably.pubsub.types.Callback; +import io.ably.pubsub.types.ClientOptions; +import io.ably.pubsub.types.ErrorInfo; +import io.ably.pubsub.types.Message; +import io.ably.pubsub.types.ProtocolMessage; +import io.ably.pubsub.util.Log; public class RealtimeMessageTest extends ParameterizedTest { @@ -73,10 +75,10 @@ public class RealtimeMessageTest extends ParameterizedTest { @Ignore("FIXME: fix exception") @Test public void single_send() { - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; try { ClientOptions opts = createOptions(testVars.keys[0].keyStr); - ably = new AblyRealtime(opts); + ably = RealtimeClientFactory.create(opts); /* create a channel */ final Channel channel = ably.channels.get("subscribe_send_binary"); @@ -118,13 +120,13 @@ public void single_send() { @Ignore("FIXME: fix exception") @Test public void single_send_noecho() { - AblyRealtime txAbly = null; - AblyRealtime rxAbly = null; + PubSubRealtimeClient txAbly = null; + PubSubRealtimeClient rxAbly = null; try { ClientOptions opts = createOptions(testVars.keys[0].keyStr); opts.echoMessages = false; - txAbly = new AblyRealtime(opts); - rxAbly = new AblyRealtime(opts); + txAbly = RealtimeClientFactory.create(opts); + rxAbly = RealtimeClientFactory.create(opts); String channelName = "subscribe_send_binary_noecho"; /* create a channel */ @@ -177,11 +179,11 @@ public void single_send_noecho() { @Ignore("FIXME: fix exception") @Test public void subscribe_implicit_attach() { - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; String channelName = "subscribe_implicit_attach_" + testParams.name; try { ClientOptions opts = createOptions(testVars.keys[0].keyStr); - ably = new AblyRealtime(opts); + ably = RealtimeClientFactory.create(opts); /* create a channel */ final Channel channel = ably.channels.get(channelName); @@ -220,10 +222,10 @@ public void subscribe_implicit_attach() { * messages on that channel */ private void _multiple_send(String channelName, int messageCount, int msgSize, boolean binary, long delay) { - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; try { ClientOptions opts = createOptions(testVars.keys[0].keyStr); - ably = new AblyRealtime(opts); + ably = RealtimeClientFactory.create(opts); /* create a channel */ final Channel channel = ably.channels.get(channelName); @@ -304,10 +306,10 @@ private void _multiple_send(String channelName, int messageCount, int msgSize, b @Ignore("FIXME: fix exception") @Test public void publish_channel_state() { - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; try { ClientOptions opts = createOptions(testVars.keys[0].keyStr); - ably = new AblyRealtime(opts); + ably = RealtimeClientFactory.create(opts); Channel pubChannel = ably.channels.get("publish_channel_state"); ChannelWaiter channelWaiter = new ChannelWaiter(pubChannel); @@ -363,10 +365,10 @@ public void publish_channel_state() { * messages on that channel */ private void _multiple_send_batch(String channelName, int messageCount, int batchCount, long batchDelay) { - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; try { ClientOptions opts = createOptions(testVars.keys[0].keyStr); - ably = new AblyRealtime(opts); + ably = RealtimeClientFactory.create(opts); /* create a channel */ final Channel channel = ably.channels.get(channelName); @@ -470,10 +472,10 @@ public void multiple_send_1000_10() { */ @Test public void single_error() { - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; try { ClientOptions opts = createOptions(testVars.keys[4].keyStr); - ably = new AblyRealtime(opts); + ably = RealtimeClientFactory.create(opts); /* create a channel; channel3 can subscribe but not publish * with this key */ @@ -503,10 +505,10 @@ public void single_error() { @Test public void ensure_disconnect_with_error_does_not_move_to_failed() { - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; try { ClientOptions opts = createOptions(testVars.keys[0].keyStr); - ably = new AblyRealtime(opts); + ably = RealtimeClientFactory.create(opts); /* wait until connected */ (new ConnectionWaiter(ably.connection)).waitFor(ConnectionState.connected); @@ -535,10 +537,10 @@ public void ensure_disconnect_with_error_does_not_move_to_failed() { public void messages_encoding_fixtures() { MessagesEncodingData fixtures; fixtures = AblyCommonsReader.read(testMessagesEncodingFile, MessagesEncodingData.class); - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; try { ClientOptions opts = createOptions(testVars.keys[0].keyStr); - ably = new AblyRealtime(opts); + ably = RealtimeClientFactory.create(opts); final Channel channel = ably.channels.get("test"); channel.attach(); @@ -562,7 +564,7 @@ public void messages_encoding_fixtures() { channel.publish(receivedMessage, msgComplete); msgComplete.waitFor(); - MessagesEncodingDataItem persistedMessage = ably.http.request(new Http.Execute() { + MessagesEncodingDataItem persistedMessage = ably.http.request(new HttpRequester.Execute() { @Override public void execute(HttpScheduler http, Callback callback) throws AblyException { http.get("/channels/" + channel.name + "/messages?limit=1", null, null, new HttpCore.ResponseHandler() { @@ -597,17 +599,17 @@ public void messages_msgpack_and_json_encoding_is_compatible() { // Publish each data type through raw JSON POST and retrieve through MsgPack and JSON. - AblyRealtime realtimeSubscribeClientMsgPack = null; - AblyRealtime realtimeSubscribeClientJson = null; + PubSubRealtimeClient realtimeSubscribeClientMsgPack = null; + PubSubRealtimeClient realtimeSubscribeClientJson = null; try { ClientOptions jsonOpts = createOptions(testVars.keys[0].keyStr); ClientOptions msgpackOpts = createOptions(testVars.keys[0].keyStr); msgpackOpts.useBinaryProtocol = !testParams.useBinaryProtocol; - AblyRest restPublishClient = new AblyRest(jsonOpts); - realtimeSubscribeClientMsgPack = new AblyRealtime(msgpackOpts); - realtimeSubscribeClientJson = new AblyRealtime(jsonOpts); + PubSubHttpClient httpPublishClient = HttpClientFactory.create(jsonOpts); + realtimeSubscribeClientMsgPack = RealtimeClientFactory.create(msgpackOpts); + realtimeSubscribeClientJson = RealtimeClientFactory.create(jsonOpts); final Channel realtimeSubscribeChannelMsgPack = realtimeSubscribeClientMsgPack.channels.get("test-subscribe"); final Channel realtimeSubscribeChannelJson = realtimeSubscribeClientJson.channels.get("test-subscribe"); @@ -620,7 +622,7 @@ public void messages_msgpack_and_json_encoding_is_compatible() { for(MessagesEncodingDataItem fixtureMessage : fixtures.messages) { MessageWaiter messageWaiter = new MessageWaiter(realtimeSubscribeChannel); - HttpHelpers.postSync(restPublishClient.http, "/channels/" + realtimeSubscribeChannel.name + "/messages", null, null, new HttpUtils.JsonRequestBody(fixtureMessage), null, true); + HttpHelpers.postSync(httpPublishClient.http, "/channels/" + realtimeSubscribeChannel.name + "/messages", null, null, new HttpUtils.JsonRequestBody(fixtureMessage), null, true); messageWaiter.waitFor(1); realtimeSubscribeChannel.unsubscribe(messageWaiter); @@ -631,19 +633,19 @@ public void messages_msgpack_and_json_encoding_is_compatible() { } } - for(AblyRealtime realtimeSubscribeClient : new AblyRealtime[]{realtimeSubscribeClientMsgPack, realtimeSubscribeClientJson}) { + for(PubSubRealtimeClient realtimeSubscribeClient : new PubSubRealtimeClient[]{realtimeSubscribeClientMsgPack, realtimeSubscribeClientJson}) { realtimeSubscribeClient.close(); realtimeSubscribeClient = null; } // Publish each data type through MsgPack and JSON and retrieve through raw JSON GET. - AblyRest restPublishClientMsgPack = new AblyRest(msgpackOpts); - AblyRest restPublishClientJson = new AblyRest(jsonOpts); - AblyRest restRetrieveClient = new AblyRest(jsonOpts); + PubSubHttpClient httpPublishClientMsgPack = HttpClientFactory.create(msgpackOpts); + PubSubHttpClient httpPublishClientJson = HttpClientFactory.create(jsonOpts); + PubSubHttpClient httpRetrieveClient = HttpClientFactory.create(jsonOpts); - final io.ably.lib.rest.Channel restPublishChannelMsgPack = restPublishClientMsgPack.channels.get("test-publish"); - final io.ably.lib.rest.Channel restPublishChannelJson = restPublishClientJson.channels.get("test-publish"); + final io.ably.pubsub.http.Channel httpPublishChannelMsgPack = httpPublishClientMsgPack.channels.get("test-publish"); + final io.ably.pubsub.http.Channel httpPublishChannelJson = httpPublishClientJson.channels.get("test-publish"); for(MessagesEncodingDataItem fixtureMessage : fixtures.messages) { Object data = fixtureMessage.expectedValue; @@ -653,13 +655,13 @@ public void messages_msgpack_and_json_encoding_is_compatible() { data = ((JsonPrimitive) data).getAsString(); } - for(final io.ably.lib.rest.Channel restPublishChannel : new io.ably.lib.rest.Channel[]{restPublishChannelMsgPack, restPublishChannelJson}) { - restPublishChannel.publish("event", data); + for(final io.ably.pubsub.http.Channel httpPublishChannel : new io.ably.pubsub.http.Channel[]{httpPublishChannelMsgPack, httpPublishChannelJson}) { + httpPublishChannel.publish("event", data); - MessagesEncodingDataItem persistedMessage = restRetrieveClient.http.request(new Http.Execute() { + MessagesEncodingDataItem persistedMessage = httpRetrieveClient.http.request(new HttpRequester.Execute() { @Override public void execute(HttpScheduler http, Callback callback) throws AblyException { - http.get("/channels/" + restPublishChannel.name + "/messages?limit=1", null, null, new HttpCore.ResponseHandler() { + http.get("/channels/" + httpPublishChannel.name + "/messages?limit=1", null, null, new HttpCore.ResponseHandler() { @Override public MessagesEncodingDataItem[] handleResponse(HttpCore.Response response, ErrorInfo error) throws AblyException { if(error != null) { @@ -691,7 +693,7 @@ public MessagesEncodingDataItem[] handleResponse(HttpCore.Response response, Err */ @Test public void message_inconsistent_encoding() { - AblyRealtime realtimeSubscribeClient = null; + PubSubRealtimeClient realtimeSubscribeClient = null; final ArrayList log = new ArrayList<>(); try { @@ -706,8 +708,8 @@ public void println(int severity, String tag, String msg, Throwable tr) { }; apiOptions.logLevel = Log.INFO; - AblyRest restPublishClient = new AblyRest(apiOptions); - realtimeSubscribeClient = new AblyRealtime(apiOptions); + PubSubHttpClient httpPublishClient = HttpClientFactory.create(apiOptions); + realtimeSubscribeClient = RealtimeClientFactory.create(apiOptions); final Channel realtimeSubscribeChannelJson = realtimeSubscribeClient.channels.get("test-encoding"); @@ -723,7 +725,7 @@ public void println(int severity, String tag, String msg, Throwable tr) { testData.expectedType = "binary"; testData.expectedHexValue = "30313233343536373839"; /* hex for "0123456789" */ - HttpHelpers.postSync(restPublishClient.http, "/channels/" + realtimeSubscribeChannelJson.name + "/messages", null, null, new HttpUtils.JsonRequestBody(testData), null, true); + HttpHelpers.postSync(httpPublishClient.http, "/channels/" + realtimeSubscribeChannelJson.name + "/messages", null, null, new HttpUtils.JsonRequestBody(testData), null, true); messageWaiter.waitFor(1); realtimeSubscribeChannelJson.unsubscribe(messageWaiter); @@ -916,7 +918,7 @@ static class MessagesData { @Ignore("FIXME: fix exception") @Test public void opaque_message_extras() throws AblyException { - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; try { final JsonObject opaqueJson = new JsonObject(); opaqueJson.addProperty("Some Property", "Lorem Ipsum"); @@ -930,7 +932,7 @@ public void opaque_message_extras() throws AblyException { message.extras = extras; final ClientOptions clientOptions = createOptions(testVars.keys[0].keyStr); - ably = new AblyRealtime(clientOptions); + ably = RealtimeClientFactory.create(clientOptions); // create a channel and attach to it final Channel channel = ably.channels.get(createChannelName("opaque_message_extras")); @@ -971,7 +973,7 @@ public void should_have_serial_action_version() throws AblyException { ClientOptions opts = createOptions(testVars.keys[7].keyStr); AtomicReference receivedMessage = new AtomicReference<>(); opts.clientId = "chat"; - try (AblyRealtime realtime = new AblyRealtime(opts)) { + try (PubSubRealtimeClient realtime = RealtimeClientFactory.create(opts)) { final Channel channel = realtime.channels.get("foo::$chat::$chatMessages"); CompletionWaiter msgComplete = new CompletionWaiter(); channel.subscribe(message -> { @@ -1010,8 +1012,8 @@ public void should_have_serial_action_version() throws AblyException { public void should_not_duplicate_messages() throws Exception { ClientOptions opts = createOptions(testVars.keys[0].keyStr); String testChannelName = "my-channel" + System.currentTimeMillis(); - try (AblyRest rest = new AblyRest(opts)) { - final io.ably.lib.rest.Channel channel = rest.channels.get(testChannelName); + try (PubSubHttpClient rest = HttpClientFactory.create(opts)) { + final io.ably.pubsub.http.Channel channel = rest.channels.get(testChannelName); Message[] messages = new Message[] { new Message("name", "message 1"), @@ -1022,7 +1024,7 @@ public void should_not_duplicate_messages() throws Exception { channel.publish(messages); } - try (AblyRealtime realtime = new AblyRealtime(opts)) { + try (PubSubRealtimeClient realtime = RealtimeClientFactory.create(opts)) { final ChannelOptions options = new ChannelOptions(); options.params = new HashMap<>(); options.params.put("rewind", "10"); @@ -1052,7 +1054,7 @@ public void should_not_duplicate_messages() throws Exception { public void should_have_annotations_and_versions() throws Exception { ClientOptions opts = createOptions(testVars.keys[7].keyStr); AtomicReference receivedMessage = new AtomicReference<>(); - try (AblyRealtime realtime = new AblyRealtime(opts)) { + try (PubSubRealtimeClient realtime = RealtimeClientFactory.create(opts)) { final Channel channel = realtime.channels.get("should_have_annotations_and_versions"); CompletionWaiter msgComplete = new CompletionWaiter(); channel.subscribe(message -> { @@ -1065,7 +1067,7 @@ public void should_have_annotations_and_versions() throws Exception { assertNull(attachListener.waitFor(1, 10_000)); /* publish to the channel */ - try (AblyRest rest = new AblyRest(opts)) { + try (PubSubHttpClient rest = HttpClientFactory.create(opts)) { Message[] messages = new Message[] { new Message("message", "hello world!"), }; diff --git a/lib/src/test/java/io/ably/lib/test/realtime/RealtimePresenceHistoryTest.java b/lib/src/test/java/io/ably/pubsub/test/realtime/RealtimePresenceHistoryTest.java similarity index 93% rename from lib/src/test/java/io/ably/lib/test/realtime/RealtimePresenceHistoryTest.java rename to lib/src/test/java/io/ably/pubsub/test/realtime/RealtimePresenceHistoryTest.java index 85cc365f4..d605516f4 100644 --- a/lib/src/test/java/io/ably/lib/test/realtime/RealtimePresenceHistoryTest.java +++ b/lib/src/test/java/io/ably/pubsub/test/realtime/RealtimePresenceHistoryTest.java @@ -1,4 +1,4 @@ -package io.ably.lib.test.realtime; +package io.ably.pubsub.test.realtime; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.is; @@ -14,26 +14,28 @@ import org.junit.Test; import org.junit.rules.Timeout; -import io.ably.lib.debug.DebugOptions; -import io.ably.lib.realtime.AblyRealtime; -import io.ably.lib.realtime.Channel; -import io.ably.lib.realtime.ChannelState; -import io.ably.lib.rest.AblyRest; -import io.ably.lib.rest.Auth; -import io.ably.lib.rest.Auth.TokenParams; -import io.ably.lib.test.common.Helpers.ChannelWaiter; -import io.ably.lib.test.common.Helpers.CompletionSet; -import io.ably.lib.test.common.Helpers.CompletionWaiter; -import io.ably.lib.test.common.Helpers.PresenceWaiter; -import io.ably.lib.test.common.Helpers.RawProtocolMonitor; -import io.ably.lib.test.common.ParameterizedTest; -import io.ably.lib.types.AblyException; -import io.ably.lib.types.ClientOptions; -import io.ably.lib.types.PaginatedResult; -import io.ably.lib.types.Param; -import io.ably.lib.types.PresenceMessage; -import io.ably.lib.types.ProtocolMessage; -import io.ably.lib.types.ProtocolMessage.Action; +import io.ably.pubsub.debug.DebugOptions; +import io.ably.pubsub.realtime.PubSubRealtimeClient; +import io.ably.pubsub.realtime.RealtimeClientFactory; +import io.ably.pubsub.realtime.Channel; +import io.ably.pubsub.realtime.ChannelState; +import io.ably.pubsub.http.HttpClientFactory; +import io.ably.pubsub.http.PubSubHttpClient; +import io.ably.pubsub.http.Auth; +import io.ably.pubsub.http.Auth.TokenParams; +import io.ably.pubsub.test.common.Helpers.ChannelWaiter; +import io.ably.pubsub.test.common.Helpers.CompletionSet; +import io.ably.pubsub.test.common.Helpers.CompletionWaiter; +import io.ably.pubsub.test.common.Helpers.PresenceWaiter; +import io.ably.pubsub.test.common.Helpers.RawProtocolMonitor; +import io.ably.pubsub.test.common.ParameterizedTest; +import io.ably.pubsub.types.AblyException; +import io.ably.pubsub.types.ClientOptions; +import io.ably.pubsub.types.PaginatedResult; +import io.ably.pubsub.types.Param; +import io.ably.pubsub.types.PresenceMessage; +import io.ably.pubsub.types.ProtocolMessage; +import io.ably.pubsub.types.ProtocolMessage.Action; import java.util.Locale; @@ -42,7 +44,7 @@ public class RealtimePresenceHistoryTest extends ParameterizedTest { private static final String testClientId = "testClientId"; private long timeOffset; - private AblyRest rest; + private PubSubHttpClient rest; private Auth.TokenDetails token; @Rule @@ -52,7 +54,7 @@ public class RealtimePresenceHistoryTest extends ParameterizedTest { public void setUpBefore() throws Exception { /* create tokens for specific clientIds */ ClientOptions opts = createOptions(testVars.keys[0].keyStr); - rest = new AblyRest(opts); + rest = HttpClientFactory.create(opts); token = rest.auth.requestToken(new TokenParams() {{ clientId = testClientId; }}, null); /* sync */ @@ -67,12 +69,12 @@ public void setUpBefore() throws Exception { */ @Test public void presencehistory_simple() { - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; try { ClientOptions rtOpts = createOptions(); rtOpts.token = token.token; rtOpts.clientId = testClientId; - ably = new AblyRealtime(rtOpts); + ably = RealtimeClientFactory.create(rtOpts); String channelName = "persisted:presencehistory_simple_" + testParams.name; String messageText = "Test message (presencehistory_simple)"; @@ -114,12 +116,12 @@ public void presencehistory_simple() { */ @Test public void presencehistory_types() { - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; try { ClientOptions rtOpts = createOptions(); rtOpts.token = token.token; rtOpts.clientId = testClientId; - ably = new AblyRealtime(rtOpts); + ably = RealtimeClientFactory.create(rtOpts); String channelName = "persisted:presencehistory_types_" + testParams.name; @@ -163,12 +165,12 @@ public void presencehistory_types() { */ @Test public void presencehistory_types_forward() { - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; try { ClientOptions rtOpts = createOptions(); rtOpts.token = token.token; rtOpts.clientId = testClientId; - ably = new AblyRealtime(rtOpts); + ably = RealtimeClientFactory.create(rtOpts); String channelName = "persisted:presencehistory_types_forward_" + testParams.name; @@ -215,15 +217,15 @@ public void presencehistory_types_forward() { */ @Test public void presencehistory_second_channel() { - AblyRealtime txAbly = null, rxAbly = null; + PubSubRealtimeClient txAbly = null, rxAbly = null; try { ClientOptions txOpts = createOptions(); txOpts.token = token.token; txOpts.clientId = testClientId; - txAbly = new AblyRealtime(txOpts); + txAbly = RealtimeClientFactory.create(txOpts); ClientOptions rxOpts = createOptions(testVars.keys[0].keyStr); - rxAbly = new AblyRealtime(rxOpts); + rxAbly = RealtimeClientFactory.create(rxOpts); String channelName = "persisted:presencehistory_second_channel_" + testParams.name; /* create a channel */ @@ -275,12 +277,12 @@ public void presencehistory_second_channel() { */ @Test public void presencehistory_wait_b() { - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; try { ClientOptions rtOpts = createOptions(); rtOpts.token = token.token; rtOpts.clientId = testClientId; - ably = new AblyRealtime(rtOpts); + ably = RealtimeClientFactory.create(rtOpts); String channelName = "persisted:presencehistory_wait_b_" + testParams.name; String messageText = "Test message (presencehistory_wait_b)"; @@ -328,12 +330,12 @@ public void presencehistory_wait_b() { */ @Test public void presencehistory_wait_f() { - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; try { ClientOptions rtOpts = createOptions(); rtOpts.token = token.token; rtOpts.clientId = testClientId; - ably = new AblyRealtime(rtOpts); + ably = RealtimeClientFactory.create(rtOpts); String channelName = "persisted:presencehistory_wait_f_" + testParams.name; String messageText = "Test message (presencehistory_wait_f)"; @@ -381,12 +383,12 @@ public void presencehistory_wait_f() { */ @Test public void presencehistory_mixed_b() { - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; try { ClientOptions rtOpts = createOptions(); rtOpts.token = token.token; rtOpts.clientId = testClientId; - ably = new AblyRealtime(rtOpts); + ably = RealtimeClientFactory.create(rtOpts); String channelName = "persisted:presencehistory_mixed_b_" + testParams.name; String persistMessageText = "test_event (persisted)"; String liveMessageText = "test_event (live)"; @@ -441,12 +443,12 @@ public void presencehistory_mixed_b() { */ @Test public void presencehistory_mixed_f() { - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; try { ClientOptions rtOpts = createOptions(); rtOpts.token = token.token; rtOpts.clientId = testClientId; - ably = new AblyRealtime(rtOpts); + ably = RealtimeClientFactory.create(rtOpts); String channelName = "persisted:presencehistory_mixed_f_" + testParams.name; String persistMessageText = "test_event (persisted)"; String liveMessageText = "test_event (live)"; @@ -498,12 +500,12 @@ public void presencehistory_mixed_f() { */ @Test public void presencehistory_limit_f() { - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; try { ClientOptions rtOpts = createOptions(); rtOpts.token = token.token; rtOpts.clientId = testClientId; - ably = new AblyRealtime(rtOpts); + ably = RealtimeClientFactory.create(rtOpts); String channelName = "persisted:presencehistory_limit_f_" + testParams.name; /* create a channel */ @@ -553,12 +555,12 @@ public void presencehistory_limit_f() { */ @Test public void presencehistory_limit_b() { - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; try { ClientOptions rtOpts = createOptions(); rtOpts.token = token.token; rtOpts.clientId = testClientId; - ably = new AblyRealtime(rtOpts); + ably = RealtimeClientFactory.create(rtOpts); String channelName = "persisted:presencehistory_limit_b_" + testParams.name; /* create a channel */ @@ -609,14 +611,14 @@ public void presencehistory_limit_b() { */ @Test public void presencehistory_time_f() { - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; try { /* first, publish some messages */ long intervalStart = 0, intervalEnd = 0; ClientOptions rtOpts = createOptions(); rtOpts.token = token.token; rtOpts.clientId = testClientId; - ably = new AblyRealtime(rtOpts); + ably = RealtimeClientFactory.create(rtOpts); String channelName = "persisted:presencehistory_time_f_" + testParams.name; /* create a channel */ @@ -676,14 +678,14 @@ public void presencehistory_time_f() { */ @Test public void presencehistory_time_b() { - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; try { /* first, publish some messages */ long intervalStart = 0, intervalEnd = 0; ClientOptions rtOpts = createOptions(); rtOpts.token = token.token; rtOpts.clientId = testClientId; - ably = new AblyRealtime(rtOpts); + ably = RealtimeClientFactory.create(rtOpts); String channelName = "persisted:presencehistory_time_b_" + testParams.name; /* create a channel */ @@ -743,12 +745,12 @@ public void presencehistory_time_b() { */ @Test public void presencehistory_paginate_f() { - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; try { ClientOptions rtOpts = createOptions(); rtOpts.token = token.token; rtOpts.clientId = testClientId; - ably = new AblyRealtime(rtOpts); + ably = RealtimeClientFactory.create(rtOpts); String channelName = "persisted:presencehistory_paginate_f_" + testParams.name; /* create a channel */ @@ -816,12 +818,12 @@ public void presencehistory_paginate_f() { */ @Test public void presencehistory_paginate_b() { - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; try { ClientOptions rtOpts = createOptions(); rtOpts.token = token.token; rtOpts.clientId = testClientId; - ably = new AblyRealtime(rtOpts); + ably = RealtimeClientFactory.create(rtOpts); String channelName = "persisted:presencehistory_paginate_b_" + testParams.name; /* create a channel */ @@ -889,12 +891,12 @@ public void presencehistory_paginate_b() { */ @Test public void presencehistory_paginate_first_f() { - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; try { ClientOptions rtOpts = createOptions(); rtOpts.token = token.token; rtOpts.clientId = testClientId; - ably = new AblyRealtime(rtOpts); + ably = RealtimeClientFactory.create(rtOpts); String channelName = "persisted:presencehistory_paginate_first_f_" + testParams.name; /* create a channel */ @@ -962,12 +964,12 @@ public void presencehistory_paginate_first_f() { */ @Test public void presencehistory_paginate_first_b() { - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; try { ClientOptions rtOpts = createOptions(); rtOpts.token = token.token; rtOpts.clientId = testClientId; - ably = new AblyRealtime(rtOpts); + ably = RealtimeClientFactory.create(rtOpts); String channelName = "persisted:presencehistory_paginate_first_b_" + testParams.name; /* create a channel */ @@ -1039,18 +1041,18 @@ public void presencehistory_paginate_first_b() { @Test @Ignore("Fails due to issues in sandbox. See https://github.com/ably/realtime/issues/1845 for details.") public void presencehistory_from_attach() { - AblyRealtime txAbly = null, rxAbly = null; + PubSubRealtimeClient txAbly = null, rxAbly = null; try { ClientOptions txOpts = createOptions(); txOpts.token = token.token; txOpts.clientId = testClientId; - txAbly = new AblyRealtime(txOpts); + txAbly = RealtimeClientFactory.create(txOpts); DebugOptions rxOpts = new DebugOptions(testVars.keys[0].keyStr); fillInOptions(rxOpts); RawProtocolMonitor rawPresenceWaiter = RawProtocolMonitor.createReceiver(Action.presence); rxOpts.protocolListener = rawPresenceWaiter; - rxAbly = new AblyRealtime(rxOpts); + rxAbly = RealtimeClientFactory.create(rxOpts); String channelName = "persisted:presencehistory_from_attach_" + testParams.name; /* create a channel */ @@ -1146,18 +1148,18 @@ public void run() { */ @Test public void presencehistory_until_attach() { - AblyRealtime txAbly = null, rxAbly = null; + PubSubRealtimeClient txAbly = null, rxAbly = null; try { ClientOptions txOpts = createOptions(); txOpts.token = token.token; txOpts.clientId = testClientId; - txAbly = new AblyRealtime(txOpts); + txAbly = RealtimeClientFactory.create(txOpts); DebugOptions rxOpts = new DebugOptions(testVars.keys[0].keyStr); fillInOptions(rxOpts); RawProtocolMonitor rawPresenceWaiter = RawProtocolMonitor.createReceiver(Action.presence); rxOpts.protocolListener = rawPresenceWaiter; - rxAbly = new AblyRealtime(rxOpts); + rxAbly = RealtimeClientFactory.create(rxOpts); String channelName = "persisted:presencehistory_until_attach_" + testParams.name; /* create a channel */ @@ -1220,7 +1222,7 @@ public void presencehistory_until_attach() { @Test(expected=AblyException.class) public void presencehistory_until_attach_before_attached() throws AblyException { ClientOptions options = createOptions(testVars.keys[0].keyStr); - AblyRealtime ably = new AblyRealtime(options); + PubSubRealtimeClient ably = RealtimeClientFactory.create(options); ably.channels.get("test").presence.history(new Param[]{ new Param("untilAttach", "true")}); ably.close(); @@ -1235,7 +1237,7 @@ public void presencehistory_until_attach_before_attached() throws AblyException @Test(expected=AblyException.class) public void presencehistory_until_attach_invalid_value() throws AblyException { ClientOptions options = createOptions(testVars.keys[0].keyStr); - AblyRealtime ably = new AblyRealtime(options); + PubSubRealtimeClient ably = RealtimeClientFactory.create(options); ably.channels.get("test").presence.history(new Param[]{ new Param("untilAttach", "affirmative")}); ably.close(); @@ -1249,12 +1251,12 @@ public void presencehistory_until_attach_invalid_value() throws AblyException { */ @Test public void presencehistory_islast() throws AblyException { - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; try { ClientOptions opts = createOptions(testVars.keys[0].keyStr); opts.token = token.token; opts.clientId = testClientId; - ably = new AblyRealtime(opts); + ably = RealtimeClientFactory.create(opts); String channelName = "persisted:presencehistory_islast_" + testParams.name; int pageMessageCount = 10; diff --git a/lib/src/test/java/io/ably/lib/test/realtime/RealtimePresenceTest.java b/lib/src/test/java/io/ably/pubsub/test/realtime/RealtimePresenceTest.java similarity index 93% rename from lib/src/test/java/io/ably/lib/test/realtime/RealtimePresenceTest.java rename to lib/src/test/java/io/ably/pubsub/test/realtime/RealtimePresenceTest.java index 2534139bd..e932cc4d0 100644 --- a/lib/src/test/java/io/ably/lib/test/realtime/RealtimePresenceTest.java +++ b/lib/src/test/java/io/ably/pubsub/test/realtime/RealtimePresenceTest.java @@ -1,4 +1,4 @@ -package io.ably.lib.test.realtime; +package io.ably.pubsub.test.realtime; import static org.hamcrest.CoreMatchers.containsString; import static org.hamcrest.Matchers.empty; @@ -29,47 +29,49 @@ import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParser; -import io.ably.lib.debug.DebugOptions; -import io.ably.lib.realtime.AblyRealtime; -import io.ably.lib.realtime.Channel; -import io.ably.lib.realtime.ChannelEvent; -import io.ably.lib.realtime.ChannelState; -import io.ably.lib.realtime.ChannelStateListener; -import io.ably.lib.realtime.CompletionListener; -import io.ably.lib.realtime.ConnectionEvent; -import io.ably.lib.realtime.ConnectionState; -import io.ably.lib.realtime.ConnectionStateListener; -import io.ably.lib.realtime.Presence; -import io.ably.lib.test.util.AblyCommonsReader; -import io.ably.lib.types.AblyException; -import io.ably.lib.types.Capability; -import io.ably.lib.types.ChannelOptions; -import io.ably.lib.types.ClientOptions; -import io.ably.lib.types.ErrorInfo; -import io.ably.lib.types.PaginatedResult; -import io.ably.lib.types.Param; -import io.ably.lib.types.PresenceMessage; -import io.ably.lib.types.ProtocolMessage; -import io.ably.lib.util.Serialisation; +import io.ably.pubsub.debug.DebugOptions; +import io.ably.pubsub.realtime.PubSubRealtimeClient; +import io.ably.pubsub.realtime.RealtimeClientFactory; +import io.ably.pubsub.realtime.Channel; +import io.ably.pubsub.realtime.ChannelEvent; +import io.ably.pubsub.realtime.ChannelState; +import io.ably.pubsub.realtime.ChannelStateListener; +import io.ably.pubsub.realtime.CompletionListener; +import io.ably.pubsub.realtime.ConnectionEvent; +import io.ably.pubsub.realtime.ConnectionState; +import io.ably.pubsub.realtime.ConnectionStateListener; +import io.ably.pubsub.realtime.Presence; +import io.ably.pubsub.test.util.AblyCommonsReader; +import io.ably.pubsub.types.AblyException; +import io.ably.pubsub.types.Capability; +import io.ably.pubsub.types.ChannelOptions; +import io.ably.pubsub.types.ClientOptions; +import io.ably.pubsub.types.ErrorInfo; +import io.ably.pubsub.types.PaginatedResult; +import io.ably.pubsub.types.Param; +import io.ably.pubsub.types.PresenceMessage; +import io.ably.pubsub.types.ProtocolMessage; +import io.ably.pubsub.util.Serialisation; import org.junit.Before; import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; import org.junit.rules.Timeout; -import io.ably.lib.rest.AblyRest; -import io.ably.lib.rest.Auth; -import io.ably.lib.rest.Auth.TokenParams; -import io.ably.lib.test.common.Helpers; -import io.ably.lib.test.common.Helpers.ChannelWaiter; -import io.ably.lib.test.common.Helpers.CompletionSet; -import io.ably.lib.test.common.Helpers.CompletionWaiter; -import io.ably.lib.test.common.Helpers.ConnectionWaiter; -import io.ably.lib.test.common.Helpers.PresenceWaiter; -import io.ably.lib.test.common.ParameterizedTest; -import io.ably.lib.test.util.MockWebsocketFactory; -import io.ably.lib.transport.ConnectionManager; -import io.ably.lib.types.PresenceMessage.Action; +import io.ably.pubsub.http.HttpClientFactory; +import io.ably.pubsub.http.PubSubHttpClient; +import io.ably.pubsub.http.Auth; +import io.ably.pubsub.http.Auth.TokenParams; +import io.ably.pubsub.test.common.Helpers; +import io.ably.pubsub.test.common.Helpers.ChannelWaiter; +import io.ably.pubsub.test.common.Helpers.CompletionSet; +import io.ably.pubsub.test.common.Helpers.CompletionWaiter; +import io.ably.pubsub.test.common.Helpers.ConnectionWaiter; +import io.ably.pubsub.test.common.Helpers.PresenceWaiter; +import io.ably.pubsub.test.common.ParameterizedTest; +import io.ably.pubsub.test.util.MockWebsocketFactory; +import io.ably.pubsub.transport.ConnectionManager; +import io.ably.pubsub.types.PresenceMessage.Action; public class RealtimePresenceTest extends ParameterizedTest { @@ -102,9 +104,9 @@ private class TestChannel { TestChannel() { try { ClientOptions opts = createOptions(testVars.keys[0].keyStr); - rest = new AblyRest(opts); - restChannel = rest.channels.get(channelName); - realtime = new AblyRealtime(opts); + rest = HttpClientFactory.create(opts); + httpChannel = rest.channels.get(channelName); + realtime = RealtimeClientFactory.create(opts); realtimeChannel = realtime.channels.get(channelName); realtimeChannel.attach(); (new ChannelWaiter(realtimeChannel)).waitFor(ChannelState.attached); @@ -117,10 +119,10 @@ void dispose() { } String channelName = random(); - AblyRest rest; - AblyRealtime realtime; - io.ably.lib.rest.Channel restChannel; - io.ably.lib.realtime.Channel realtimeChannel; + PubSubHttpClient rest; + PubSubRealtimeClient realtime; + io.ably.pubsub.http.Channel httpChannel; + io.ably.pubsub.realtime.Channel realtimeChannel; } @Rule @@ -130,7 +132,7 @@ void dispose() { public void setUpBefore() throws Exception { /* create tokens for specific clientIds */ ClientOptions opts = createOptions(testVars.keys[0].keyStr); - AblyRest rest = new AblyRest(opts); + PubSubHttpClient rest = HttpClientFactory.create(opts); token1 = rest.auth.requestToken(new TokenParams() {{ clientId = testClientId1; }}, null); token2 = rest.auth.requestToken(new TokenParams() {{ clientId = testClientId2; }}, null); wildcardToken = rest.auth.requestToken(new TokenParams() {{ clientId = "*"; }}, null); @@ -141,7 +143,7 @@ public void setUpBefore() throws Exception { */ @Test public void enter_simple() { - AblyRealtime clientAbly1 = null; + PubSubRealtimeClient clientAbly1 = null; TestChannel testChannel = new TestChannel(); try { /* subscribe for presence events in the anonymous connection */ @@ -152,7 +154,7 @@ public void enter_simple() { clientId = testClientId1; }}; fillInOptions(client1Opts); - clientAbly1 = new AblyRealtime(client1Opts); + clientAbly1 = RealtimeClientFactory.create(client1Opts); /* wait until connected */ (new ConnectionWaiter(clientAbly1.connection)).waitFor(ConnectionState.connected); @@ -191,7 +193,7 @@ public void enter_simple() { */ @Test public void enter_before_attach() { - AblyRealtime clientAbly1 = null; + PubSubRealtimeClient clientAbly1 = null; TestChannel testChannel = new TestChannel(); try { /* subscribe for presence events in the anonymous connection */ @@ -202,7 +204,7 @@ public void enter_before_attach() { clientId = testClientId1; }}; fillInOptions(client1Opts); - clientAbly1 = new AblyRealtime(client1Opts); + clientAbly1 = RealtimeClientFactory.create(client1Opts); /* wait until connected */ (new ConnectionWaiter(clientAbly1.connection)).waitFor(ConnectionState.connected); @@ -239,7 +241,7 @@ public void enter_before_attach() { */ @Test public void enter_before_connect() { - AblyRealtime clientAbly1 = null; + PubSubRealtimeClient clientAbly1 = null; TestChannel testChannel = new TestChannel(); try { /* subscribe for presence events in the anonymous connection */ @@ -250,7 +252,7 @@ public void enter_before_connect() { clientId = testClientId1; }}; fillInOptions(client1Opts); - clientAbly1 = new AblyRealtime(client1Opts); + clientAbly1 = RealtimeClientFactory.create(client1Opts); /* get channel */ Channel client1Channel = clientAbly1.channels.get(testChannel.channelName); @@ -284,7 +286,7 @@ public void enter_before_connect() { */ @Test public void enter_leave_simple() { - AblyRealtime clientAbly1 = null; + PubSubRealtimeClient clientAbly1 = null; TestChannel testChannel = new TestChannel(); try { /* subscribe for presence events in the anonymous connection */ @@ -295,7 +297,7 @@ public void enter_leave_simple() { clientId = testClientId1; }}; fillInOptions(client1Opts); - clientAbly1 = new AblyRealtime(client1Opts); + clientAbly1 = RealtimeClientFactory.create(client1Opts); /* get channel */ Channel client1Channel = clientAbly1.channels.get(testChannel.channelName); @@ -343,7 +345,7 @@ public void enter_leave_simple() { */ @Test public void enter_enter_simple() { - AblyRealtime clientAbly1 = null; + PubSubRealtimeClient clientAbly1 = null; TestChannel testChannel = new TestChannel(); try { /* subscribe for presence events in the anonymous connection */ @@ -354,7 +356,7 @@ public void enter_enter_simple() { clientId = testClientId1; }}; fillInOptions(client1Opts); - clientAbly1 = new AblyRealtime(client1Opts); + clientAbly1 = RealtimeClientFactory.create(client1Opts); /* get channel */ Channel client1Channel = clientAbly1.channels.get(testChannel.channelName); @@ -411,7 +413,7 @@ public void enter_enter_simple() { */ @Test public void enter_update_simple() { - AblyRealtime clientAbly1 = null; + PubSubRealtimeClient clientAbly1 = null; TestChannel testChannel = new TestChannel(); try { /* subscribe for presence events in the anonymous connection */ @@ -422,7 +424,7 @@ public void enter_update_simple() { clientId = testClientId1; }}; fillInOptions(client1Opts); - clientAbly1 = new AblyRealtime(client1Opts); + clientAbly1 = RealtimeClientFactory.create(client1Opts); /* get channel */ Channel client1Channel = clientAbly1.channels.get(testChannel.channelName); @@ -479,7 +481,7 @@ public void enter_update_simple() { */ @Test public void enter_update_null() { - AblyRealtime clientAbly1 = null; + PubSubRealtimeClient clientAbly1 = null; TestChannel testChannel = new TestChannel(); try { /* subscribe for presence events in the anonymous connection */ @@ -491,7 +493,7 @@ public void enter_update_null() { }}; fillInOptions(client1Opts); client1Opts.useBinaryProtocol = true; - clientAbly1 = new AblyRealtime(client1Opts); + clientAbly1 = RealtimeClientFactory.create(client1Opts); /* get channel */ Channel client1Channel = clientAbly1.channels.get(testChannel.channelName); @@ -548,7 +550,7 @@ public void enter_update_null() { */ @Test public void update_noenter() { - AblyRealtime clientAbly1 = null; + PubSubRealtimeClient clientAbly1 = null; TestChannel testChannel = new TestChannel(); try { /* subscribe for presence events in the anonymous connection */ @@ -559,7 +561,7 @@ public void update_noenter() { clientId = testClientId1; }}; fillInOptions(client1Opts); - clientAbly1 = new AblyRealtime(client1Opts); + clientAbly1 = RealtimeClientFactory.create(client1Opts); /* get channel */ Channel client1Channel = clientAbly1.channels.get(testChannel.channelName); @@ -606,7 +608,7 @@ public void update_noenter() { */ @Test public void enter_leave_nodata() { - AblyRealtime clientAbly1 = null; + PubSubRealtimeClient clientAbly1 = null; TestChannel testChannel = new TestChannel(); try { /* subscribe for presence events in the anonymous connection */ @@ -617,7 +619,7 @@ public void enter_leave_nodata() { clientId = testClientId1; }}; fillInOptions(client1Opts); - clientAbly1 = new AblyRealtime(client1Opts); + clientAbly1 = RealtimeClientFactory.create(client1Opts); /* get channel */ Channel client1Channel = clientAbly1.channels.get(testChannel.channelName); @@ -661,7 +663,7 @@ public void enter_leave_nodata() { */ @Test public void realtime_get_simple() { - AblyRealtime clientAbly1 = null; + PubSubRealtimeClient clientAbly1 = null; TestChannel testChannel = new TestChannel(); try { /* subscribe for presence events in the anonymous connection */ @@ -673,7 +675,7 @@ public void realtime_get_simple() { clientId = testClientId1; }}; fillInOptions(client1Opts); - clientAbly1 = new AblyRealtime(client1Opts); + clientAbly1 = RealtimeClientFactory.create(client1Opts); /* wait until connected */ (new ConnectionWaiter(clientAbly1.connection)).waitFor(ConnectionState.connected); @@ -715,7 +717,7 @@ public void realtime_get_simple() { */ @Test public void realtime_get_leave() { - AblyRealtime clientAbly1 = null; + PubSubRealtimeClient clientAbly1 = null; TestChannel testChannel = new TestChannel(); try { /* subscribe for presence events in the anonymous connection */ @@ -726,7 +728,7 @@ public void realtime_get_leave() { clientId = testClientId1; }}; fillInOptions(client1Opts); - clientAbly1 = new AblyRealtime(client1Opts); + clientAbly1 = RealtimeClientFactory.create(client1Opts); /* wait until connected */ (new ConnectionWaiter(clientAbly1.connection)).waitFor(ConnectionState.connected); @@ -773,8 +775,8 @@ public void realtime_get_leave() { */ @Test public void attach_enter_simple() { - AblyRealtime clientAbly1 = null; - AblyRealtime clientAbly2 = null; + PubSubRealtimeClient clientAbly1 = null; + PubSubRealtimeClient clientAbly2 = null; TestChannel testChannel = new TestChannel(); try { /* subscribe for presence events in the anonymous connection */ @@ -785,7 +787,7 @@ public void attach_enter_simple() { clientId = testClientId1; }}; fillInOptions(client1Opts); - clientAbly1 = new AblyRealtime(client1Opts); + clientAbly1 = RealtimeClientFactory.create(client1Opts); /* wait until connected */ (new ConnectionWaiter(clientAbly1.connection)).waitFor(ConnectionState.connected); @@ -810,7 +812,7 @@ public void attach_enter_simple() { clientId = testClientId2; }}; fillInOptions(client2Opts); - clientAbly2 = new AblyRealtime(client2Opts); + clientAbly2 = RealtimeClientFactory.create(client2Opts); /* wait until connected */ (new ConnectionWaiter(clientAbly2.connection)).waitFor(ConnectionState.connected); @@ -849,8 +851,8 @@ public void attach_enter_simple() { */ @Test public void attach_enter_multiple() { - AblyRealtime clientAbly1 = null; - AblyRealtime clientAbly2 = null; + PubSubRealtimeClient clientAbly1 = null; + PubSubRealtimeClient clientAbly2 = null; TestChannel testChannel = new TestChannel(); int clientCount = 250; try { @@ -861,7 +863,7 @@ public void attach_enter_multiple() { tokenDetails = wildcardToken; }}; fillInOptions(client1Opts); - clientAbly1 = new AblyRealtime(client1Opts); + clientAbly1 = RealtimeClientFactory.create(client1Opts); /* wait until connected */ (new ConnectionWaiter(clientAbly1.connection)).waitFor(ConnectionState.connected); @@ -888,7 +890,7 @@ public void attach_enter_multiple() { clientId = testClientId2; }}; fillInOptions(client2Opts); - clientAbly2 = new AblyRealtime(client2Opts); + clientAbly2 = RealtimeClientFactory.create(client2Opts); /* wait until connected */ (new ConnectionWaiter(clientAbly2.connection)).waitFor(ConnectionState.connected); @@ -933,8 +935,8 @@ public void attach_enter_multiple() { * both members in presence returned by realtime get() */ @Test public void realtime_enter_multiple() { - AblyRealtime clientAbly1 = null; - AblyRealtime clientAbly2 = null; + PubSubRealtimeClient clientAbly1 = null; + PubSubRealtimeClient clientAbly2 = null; TestChannel testChannel = new TestChannel(); try { /* subscribe for presence events in the anonymous connection */ @@ -946,7 +948,7 @@ public void realtime_enter_multiple() { clientId = testClientId1; }}; fillInOptions(client1Opts); - clientAbly1 = new AblyRealtime(client1Opts); + clientAbly1 = RealtimeClientFactory.create(client1Opts); /* get channel and attach */ Channel client1Channel = clientAbly1.channels.get(testChannel.channelName); @@ -962,7 +964,7 @@ public void realtime_enter_multiple() { clientId = testClientId2; }}; fillInOptions(client2Opts); - clientAbly2 = new AblyRealtime(client2Opts); + clientAbly2 = RealtimeClientFactory.create(client2Opts); /* get channel and subscribe to presence */ Channel client2Channel = clientAbly2.channels.get(testChannel.channelName); @@ -1003,7 +1005,7 @@ public void realtime_enter_multiple() { */ @Test public void rest_get_simple() { - AblyRealtime clientAbly1 = null; + PubSubRealtimeClient clientAbly1 = null; TestChannel testChannel = new TestChannel(); try { /* subscribe for presence events in the anonymous connection */ @@ -1014,7 +1016,7 @@ public void rest_get_simple() { clientId = testClientId1; }}; fillInOptions(client1Opts); - clientAbly1 = new AblyRealtime(client1Opts); + clientAbly1 = RealtimeClientFactory.create(client1Opts); /* wait until connected */ (new ConnectionWaiter(clientAbly1.connection)).waitFor(ConnectionState.connected); @@ -1034,7 +1036,7 @@ public void rest_get_simple() { assertTrue("Verify enter callback called on completion", enterComplete.success); /* get presence set and verify client present */ - PresenceMessage[] presences = testChannel.restChannel.presence.get(null).items(); + PresenceMessage[] presences = testChannel.httpChannel.presence.get(null).items(); PresenceMessage expectedPresent = contains(presences, testClientId1, Action.present); assertNotNull("Verify expected client is in presence set", expectedPresent); assertEquals(expectedPresent.data, enterString); @@ -1055,7 +1057,7 @@ public void rest_get_simple() { */ @Test public void rest_get_leave() { - AblyRealtime clientAbly1 = null; + PubSubRealtimeClient clientAbly1 = null; TestChannel testChannel = new TestChannel(); try { /* subscribe for presence events in the anonymous connection */ @@ -1066,7 +1068,7 @@ public void rest_get_leave() { clientId = testClientId1; }}; fillInOptions(client1Opts); - clientAbly1 = new AblyRealtime(client1Opts); + clientAbly1 = RealtimeClientFactory.create(client1Opts); /* wait until connected */ (new ConnectionWaiter(clientAbly1.connection)).waitFor(ConnectionState.connected); @@ -1093,7 +1095,7 @@ public void rest_get_leave() { assertTrue("Verify leave callback called on completion", leaveComplete.success); /* get presence set and verify client absent */ - PresenceMessage[] presences = testChannel.restChannel.presence.get(null).items(); + PresenceMessage[] presences = testChannel.httpChannel.presence.get(null).items(); assertNull("Verify expected client is in presence set", contains(presences, testClientId1)); } catch(AblyException e) { @@ -1112,8 +1114,8 @@ public void rest_get_leave() { * both members in presence returned by rest get() */ @Test public void rest_enter_multiple() { - AblyRealtime clientAbly1 = null; - AblyRealtime clientAbly2 = null; + PubSubRealtimeClient clientAbly1 = null; + PubSubRealtimeClient clientAbly2 = null; TestChannel testChannel = new TestChannel(); try { /* subscribe for presence events in the anonymous connection */ @@ -1124,7 +1126,7 @@ public void rest_enter_multiple() { clientId = testClientId1; }}; fillInOptions(client1Opts); - clientAbly1 = new AblyRealtime(client1Opts); + clientAbly1 = RealtimeClientFactory.create(client1Opts); /* get channel and attach */ Channel client1Channel = clientAbly1.channels.get(testChannel.channelName); @@ -1140,7 +1142,7 @@ public void rest_enter_multiple() { clientId = testClientId2; }}; fillInOptions(client2Opts); - clientAbly2 = new AblyRealtime(client2Opts); + clientAbly2 = RealtimeClientFactory.create(client2Opts); /* get channel and subscribe to presence */ Channel client2Channel = clientAbly2.channels.get(testChannel.channelName); @@ -1151,7 +1153,7 @@ public void rest_enter_multiple() { assertTrue("Verify enter callback called on completion", enter2Complete.success); /* get presence set and verify client present */ - PresenceMessage[] presences = testChannel.restChannel.presence.get(null).items(); + PresenceMessage[] presences = testChannel.httpChannel.presence.get(null).items(); PresenceMessage expectedPresent1 = contains(presences, testClientId1, Action.present); PresenceMessage expectedPresent2 = contains(presences, testClientId2, Action.present); assertNotNull("Verify expected clients are in presence set", expectedPresent1); @@ -1177,7 +1179,7 @@ public void rest_enter_multiple() { * retrieving members using paginated rest get() */ @Test public void rest_paginated_get() { - AblyRealtime clientAbly1 = null; + PubSubRealtimeClient clientAbly1 = null; TestChannel testChannel = new TestChannel(); int clientCount = 30; long delay = 100L; @@ -1189,7 +1191,7 @@ public void rest_paginated_get() { tokenDetails = wildcardToken; }}; fillInOptions(client1Opts); - clientAbly1 = new AblyRealtime(client1Opts); + clientAbly1 = RealtimeClientFactory.create(client1Opts); /* get channel and attach */ Channel client1Channel = clientAbly1.channels.get(testChannel.channelName); @@ -1205,7 +1207,7 @@ public void rest_paginated_get() { /* get the presence for this channel */ HashMap memberIndex = new HashMap(); - PaginatedResult members = testChannel.restChannel.presence.get(new Param[] { new Param("limit", "10") }); + PaginatedResult members = testChannel.httpChannel.presence.get(new Param[] { new Param("limit", "10") }); assertNotNull("Expected non-null messages", members); assertEquals("Expected 10 messages", members.items().length, 10); @@ -1262,7 +1264,7 @@ public void rest_paginated_get() { */ @Test public void disconnect_leave() { - AblyRealtime clientAbly1 = null; + PubSubRealtimeClient clientAbly1 = null; TestChannel testChannel = new TestChannel(); boolean requiresClose = false; try { @@ -1274,7 +1276,7 @@ public void disconnect_leave() { clientId = testClientId1; }}; fillInOptions(client1Opts); - clientAbly1 = new AblyRealtime(client1Opts); + clientAbly1 = RealtimeClientFactory.create(client1Opts); requiresClose = true; /* get channel */ @@ -1326,9 +1328,9 @@ public void disconnect_leave() { @Test public void realtime_presence_unsubscribe_all() throws AblyException { /* Ably instance that will emit presence events */ - AblyRealtime ably1 = null; + PubSubRealtimeClient ably1 = null; /* Ably instance that will receive presence events */ - AblyRealtime ably2 = null; + PubSubRealtimeClient ably2 = null; String channelName = "test.presence.unsubscribe.all" + System.currentTimeMillis(); @@ -1338,8 +1340,8 @@ public void realtime_presence_unsubscribe_all() throws AblyException { ClientOptions option2 = createOptions(testVars.keys[0].keyStr); option2.clientId = "receiver client"; - ably1 = new AblyRealtime(option1); - ably2 = new AblyRealtime(option2); + ably1 = RealtimeClientFactory.create(option1); + ably2 = RealtimeClientFactory.create(option2); Channel channel1 = ably1.channels.get(channelName); channel1.attach(); @@ -1404,9 +1406,9 @@ public Presence.PresenceListener setMessageStack(List messageSt @Test public void realtime_presence_unsubscribe_single() throws AblyException { /* Ably instance that will emit presence events */ - AblyRealtime ably1 = null; + PubSubRealtimeClient ably1 = null; /* Ably instance that will receive presence events */ - AblyRealtime ably2 = null; + PubSubRealtimeClient ably2 = null; String channelName = "test.presence.unsubscribe.single" + System.currentTimeMillis(); @@ -1416,8 +1418,8 @@ public void realtime_presence_unsubscribe_single() throws AblyException { ClientOptions option2 = createOptions(testVars.keys[0].keyStr); option2.clientId = "receiver client"; - ably1 = new AblyRealtime(option1); - ably2 = new AblyRealtime(option2); + ably1 = RealtimeClientFactory.create(option1); + ably2 = RealtimeClientFactory.create(option2); Channel channel1 = ably1.channels.get(channelName); channel1.attach(); @@ -1483,9 +1485,9 @@ public Presence.PresenceListener setMessageStack(List messageSt @Test public void realtime_presence_subscribe_all() throws AblyException { /* Ably instance that will emit presence events */ - AblyRealtime ably1 = null; + PubSubRealtimeClient ably1 = null; /* Ably instance that will receive presence events */ - AblyRealtime ably2 = null; + PubSubRealtimeClient ably2 = null; String channelName = "test.presence.subscribe.all" + System.currentTimeMillis(); @@ -1495,8 +1497,8 @@ public void realtime_presence_subscribe_all() throws AblyException { ClientOptions option2 = createOptions(testVars.keys[0].keyStr); option2.clientId = "receiver client"; - ably1 = new AblyRealtime(option1); - ably2 = new AblyRealtime(option2); + ably1 = RealtimeClientFactory.create(option1); + ably2 = RealtimeClientFactory.create(option2); Channel channel1 = ably1.channels.get(channelName); channel1.attach(); @@ -1558,9 +1560,9 @@ public Presence.PresenceListener setMessageStack(List messageSt @Test public void realtime_presence_subscribe_multiple() throws AblyException { /* Ably instance that will emit presence events */ - AblyRealtime ably1 = null; + PubSubRealtimeClient ably1 = null; /* Ably instance that will receive presence events */ - AblyRealtime ably2 = null; + PubSubRealtimeClient ably2 = null; String channelName = "test.presence.subscribe.multiple" + System.currentTimeMillis(); EnumSet actions = EnumSet.of(Action.update, Action.leave); @@ -1571,8 +1573,8 @@ public void realtime_presence_subscribe_multiple() throws AblyException { ClientOptions option2 = createOptions(testVars.keys[0].keyStr); option2.clientId = "receiver client"; - ably1 = new AblyRealtime(option1); - ably2 = new AblyRealtime(option2); + ably1 = RealtimeClientFactory.create(option1); + ably2 = RealtimeClientFactory.create(option2); Channel channel1 = ably1.channels.get(channelName); channel1.attach(); @@ -1634,11 +1636,11 @@ public void onPresenceMessage(PresenceMessage message) { @Test public void presence_subscribe_without_implicit_attach() { String ablyChannel = "subscribe_" + testParams.name; - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; try { ClientOptions option1 = createOptions(testVars.keys[0].keyStr); option1.clientId = "client1"; - ably = new AblyRealtime(option1); + ably = RealtimeClientFactory.create(option1); /* create a channel and set attachOnSubscribe to false */ final Channel channel = ably.channels.get(ablyChannel); @@ -1695,7 +1697,7 @@ public void presence_subscribe_without_implicit_attach_and_completion_listener_t String ablyChannel = "subscribe_" + testParams.name; ClientOptions option1 = createOptions(testVars.keys[0].keyStr); option1.clientId = "client1"; - try (AblyRealtime ably = new AblyRealtime(option1)) { + try (PubSubRealtimeClient ably = RealtimeClientFactory.create(option1)) { /* create a channel and set attachOnSubscribe to false */ final Channel channel = ably.channels.get(ablyChannel); ChannelOptions chOpts = new ChannelOptions(); @@ -1729,9 +1731,9 @@ public void presence_subscribe_without_implicit_attach_and_completion_listener_t @Test public void realtime_presence_update_multiple_queued_messages() throws AblyException { /* Ably instance that will emit presence events */ - AblyRealtime ably1 = null; + PubSubRealtimeClient ably1 = null; /* Ably instance that will receive presence events */ - AblyRealtime ably2 = null; + PubSubRealtimeClient ably2 = null; String channelName = "test.presence.subscribe.update_multiple_queued_messages" + System.currentTimeMillis(); EnumSet actions = EnumSet.of(Action.update, Action.enter); @@ -1742,8 +1744,8 @@ public void realtime_presence_update_multiple_queued_messages() throws AblyExcep ClientOptions option2 = createOptions(testVars.keys[0].keyStr); option2.clientId = "receiver client"; - ably1 = new AblyRealtime(option1); - ably2 = new AblyRealtime(option2); + ably1 = RealtimeClientFactory.create(option1); + ably2 = RealtimeClientFactory.create(option2); Channel channel1 = ably1.channels.get(channelName); @@ -1821,9 +1823,9 @@ public void onPresenceMessage(PresenceMessage message) { @Test public void realtime_presence_subscribe_single() throws AblyException { /* Ably instance that will emit presence events */ - AblyRealtime ably1 = null; + PubSubRealtimeClient ably1 = null; /* Ably instance that will receive presence events */ - AblyRealtime ably2 = null; + PubSubRealtimeClient ably2 = null; String channelName = "test.presence.subscribe.single." + System.currentTimeMillis(); PresenceMessage.Action action = Action.enter; @@ -1834,8 +1836,8 @@ public void realtime_presence_subscribe_single() throws AblyException { ClientOptions option2 = createOptions(testVars.keys[0].keyStr); option2.clientId = "receiver client"; - ably1 = new AblyRealtime(option1); - ably2 = new AblyRealtime(option2); + ably1 = RealtimeClientFactory.create(option1); + ably2 = RealtimeClientFactory.create(option2); Channel channel1 = ably1.channels.get(channelName); channel1.attach(); @@ -1900,10 +1902,10 @@ public Presence.PresenceListener setMessageStack(List messageSt */ @Test public void realtime_presence_attach_implicit_subscribe_fail() throws AblyException { - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; try { ClientOptions optsForToken = createOptions(testVars.keys[0].keyStr); - final AblyRest ablyForToken = new AblyRest(optsForToken); + final PubSubHttpClient ablyForToken = HttpClientFactory.create(optsForToken); final String channelName = "realtime_presence_attach_implicit_subscribe_fail" + testParams.name; /* get first token */ @@ -1931,7 +1933,7 @@ public void realtime_presence_attach_implicit_subscribe_fail() throws AblyExcept opts.autoConnect = false; opts.tokenDetails = token; opts.clientId = testClientId1; - ably = new AblyRealtime(opts); + ably = RealtimeClientFactory.create(opts); final ArrayList presenceMessages = new ArrayList<>(); Presence.PresenceListener listener = new Presence.PresenceListener() { @@ -2023,11 +2025,11 @@ public void onConnectionStateChanged(ConnectionStateChange state) { */ @Test public void realtime_presence_attach_implicit_enter_fail() throws AblyException { - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; try { ClientOptions opts = createOptions(testVars.keys[1].keyStr); opts.clientId = "theClient"; - ably = new AblyRealtime(opts); + ably = RealtimeClientFactory.create(opts); /* wait until connected */ new ConnectionWaiter(ably.connection).waitFor(ConnectionState.connected); @@ -2063,10 +2065,10 @@ public void realtime_presence_attach_implicit_enter_fail() throws AblyException */ @Test public void realtime_presence_attach_implicit_get_fail() throws AblyException { - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; try { ClientOptions opts = createOptions(testVars.keys[1].keyStr); - ably = new AblyRealtime(opts); + ably = RealtimeClientFactory.create(opts); /* wait until connected */ new ConnectionWaiter(ably.connection).waitFor(ConnectionState.connected); @@ -2100,10 +2102,10 @@ public void realtime_presence_attach_implicit_get_fail() throws AblyException { */ @Test public void realtime_presence_attach_implicit_enterclient_fail() throws AblyException { - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; try { ClientOptions opts = createOptions(testVars.keys[1].keyStr); - ably = new AblyRealtime(opts); + ably = RealtimeClientFactory.create(opts); /* wait until connected */ new ConnectionWaiter(ably.connection).waitFor(ConnectionState.connected); @@ -2140,10 +2142,10 @@ public void realtime_presence_attach_implicit_enterclient_fail() throws AblyExce */ @Test public void realtime_presence_attach_implicit_updateclient_fail() throws AblyException { - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; try { ClientOptions opts = createOptions(testVars.keys[1].keyStr); - ably = new AblyRealtime(opts); + ably = RealtimeClientFactory.create(opts); /* wait until connected */ new ConnectionWaiter(ably.connection).waitFor(ConnectionState.connected); @@ -2180,10 +2182,10 @@ public void realtime_presence_attach_implicit_updateclient_fail() throws AblyExc */ @Test public void realtime_presence_attach_implicit_leaveclient_fail() throws AblyException { - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; try { ClientOptions opts = createOptions(testVars.keys[1].keyStr); - ably = new AblyRealtime(opts); + ably = RealtimeClientFactory.create(opts); /* wait until connected */ new ConnectionWaiter(ably.connection).waitFor(ConnectionState.connected); @@ -2217,10 +2219,10 @@ public void realtime_presence_attach_implicit_leaveclient_fail() throws AblyExce */ @Test public void realtime_presence_get_throws_when_channel_failed() throws AblyException { - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; try { ClientOptions opts = createOptions(testVars.keys[1].keyStr); - ably = new AblyRealtime(opts); + ably = RealtimeClientFactory.create(opts); /* wait until connected */ new ConnectionWaiter(ably.connection).waitFor(ConnectionState.connected); @@ -2259,7 +2261,7 @@ public void realtime_presence_suspended_reenter() throws Exception { final String channelName = "presence_suspended_reenter" + testParams.name; mockTransport.allowSend(); - try (AblyRealtime ably = new AblyRealtime(opts)) { + try (PubSubRealtimeClient ably = RealtimeClientFactory.create(opts)) { ConnectionWaiter connectionWaiter = new ConnectionWaiter(ably.connection); connectionWaiter.waitFor(ConnectionState.connected); @@ -2316,12 +2318,12 @@ public void onPresenceMessage(PresenceMessage message) { PaginatedResult presentMembers; - try (AblyRest restClient = new AblyRest(opts)) { + try (PubSubHttpClient httpClient = HttpClientFactory.create(opts)) { long timeout = 10_000; - presentMembers = restClient.channels.get(channelName).presence.get(null); + presentMembers = httpClient.channels.get(channelName).presence.get(null); while (presentMembers.items().length != 1 && System.currentTimeMillis() - reconnectTimestamp < timeout) { Thread.sleep(250); - presentMembers = restClient.channels.get(channelName).presence.get(null); + presentMembers = httpClient.channels.get(channelName).presence.get(null); } } @@ -2347,10 +2349,10 @@ public void onPresenceMessage(PresenceMessage message) { */ @Test public void realtime_presence_map_test() { - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; try { ClientOptions opts = createOptions(testVars.keys[0].keyStr); - ably = new AblyRealtime(opts); + ably = RealtimeClientFactory.create(opts); final String channelName = "newness_comparison_" + testParams.name; Channel channel = ably.channels.get(channelName); channel.attach(); @@ -2503,8 +2505,8 @@ public void onPresenceMessage(PresenceMessage message) { */ @Test public void reattach_resume_broken_sync() { - AblyRealtime clientAbly1 = null; - AblyRealtime clientAbly2 = null; + PubSubRealtimeClient clientAbly1 = null; + PubSubRealtimeClient clientAbly2 = null; TestChannel testChannel = new TestChannel(); int clientCount = 150; /* Should be greater than 100 to break sync into several messages */ try { @@ -2515,7 +2517,7 @@ public void reattach_resume_broken_sync() { ClientOptions client1Opts = new ClientOptions(testVars.keys[0].keyStr); fillInOptions(client1Opts); client1Opts.tokenDetails = wildcardToken; - clientAbly1 = new AblyRealtime(client1Opts); + clientAbly1 = RealtimeClientFactory.create(client1Opts); /* wait until connected */ (new ConnectionWaiter(clientAbly1.connection)).waitFor(ConnectionState.connected); @@ -2546,7 +2548,7 @@ public void reattach_resume_broken_sync() { client2Opts.autoConnect = false; mockTransport20.allowSend(); - clientAbly2 = new AblyRealtime(client2Opts); + clientAbly2 = RealtimeClientFactory.create(client2Opts); /* wait until connected */ ConnectionWaiter connectionWaiter = new ConnectionWaiter(clientAbly2.connection); @@ -2616,10 +2618,10 @@ public void onError(ErrorInfo reason) { */ @Test public void presence_sync() { - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; try { ClientOptions opts = createOptions(testVars.keys[0].keyStr); - ably = new AblyRealtime(opts); + ably = RealtimeClientFactory.create(opts); final String channelName = "presence_sync_test" + testParams.name; @@ -2769,7 +2771,7 @@ public void onPresenceMessage(PresenceMessage message) { @Ignore("FIXME: fix exception") @Test public void presence_state_change () { - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; try { DebugOptions opts = new DebugOptions(testVars.keys[0].keyStr); fillInOptions(opts); @@ -2777,7 +2779,7 @@ public void presence_state_change () { final MockWebsocketFactory mockTransport = new MockWebsocketFactory(); opts.transportFactory = mockTransport; - ably = new AblyRealtime(opts); + ably = RealtimeClientFactory.create(opts); final String channelName = "presence_state_change" + testParams.name; Channel channel = ably.channels.get(channelName); @@ -2886,13 +2888,13 @@ public void onChannelStateChanged(ChannelStateChange stateChange) { @Test public void presence_without_subscribe_capability() throws AblyException { String channelName = "presence_without_subscribe" + testParams.name; - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; String presenceData = "presence_test_data"; try { /* init ably for token */ ClientOptions optsForToken = createOptions(testVars.keys[0].keyStr); - final AblyRest ablyForToken = new AblyRest(optsForToken); + final PubSubHttpClient ablyForToken = HttpClientFactory.create(optsForToken); /* get first token */ Auth.TokenParams tokenParams = new Auth.TokenParams(); @@ -2909,7 +2911,7 @@ public void presence_without_subscribe_capability() throws AblyException { ClientOptions opts = createOptions(); opts.clientId = testClientId1; opts.tokenDetails = token; - ably = new AblyRealtime(opts); + ably = RealtimeClientFactory.create(opts); Channel channel = ably.channels.get(channelName); channel.attach(); @@ -2948,12 +2950,12 @@ public void onError(ErrorInfo reason) { */ @Test public void sync_complete() { - AblyRealtime ably1 = null, ably2 = null; + PubSubRealtimeClient ably1 = null, ably2 = null; final String channelName = "sync_complete" + testParams.name; try { ClientOptions opts = createOptions(testVars.keys[0].keyStr); - ably1 = new AblyRealtime(opts); - ably2 = new AblyRealtime(opts); + ably1 = RealtimeClientFactory.create(opts); + ably2 = RealtimeClientFactory.create(opts); Channel channel1 = ably1.channels.get(channelName); channel1.presence.enterClient(testClientId1); @@ -2984,12 +2986,12 @@ public void sync_complete() { @Test public void presence_enter_without_permission() throws AblyException { String channelName = "presence_enter_without_permission" + testParams.name; - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; try { /* init ably for token */ ClientOptions optsForToken = createOptions(testVars.keys[0].keyStr); - final AblyRest ablyForToken = new AblyRest(optsForToken); + final PubSubHttpClient ablyForToken = HttpClientFactory.create(optsForToken); /* get first token */ Auth.TokenParams tokenParams = new Auth.TokenParams(); @@ -3004,7 +3006,7 @@ public void presence_enter_without_permission() throws AblyException { ClientOptions opts = createOptions(); opts.clientId = testClientId1; opts.tokenDetails = token; - ably = new AblyRealtime(opts); + ably = RealtimeClientFactory.create(opts); Channel channel = ably.channels.get(channelName); ChannelWaiter channelWaiter = new ChannelWaiter(channel); @@ -3028,12 +3030,12 @@ public void presence_enter_without_permission() throws AblyException { @Test public void presence_enter_mismatched_clientid() throws AblyException { String channelName = "presence_enter_mismatched_clientid" + testParams.name; - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; try { /* init ably for token */ ClientOptions optsForToken = createOptions(testVars.keys[0].keyStr); - final AblyRest ablyForToken = new AblyRest(optsForToken); + final PubSubHttpClient ablyForToken = HttpClientFactory.create(optsForToken); /* get first token */ Auth.TokenParams tokenParams = new Auth.TokenParams(); @@ -3049,7 +3051,7 @@ public void presence_enter_mismatched_clientid() throws AblyException { ClientOptions opts = createOptions(); opts.clientId = testClientId1; opts.tokenDetails = token; - ably = new AblyRealtime(opts); + ably = RealtimeClientFactory.create(opts); Channel channel = ably.channels.get(channelName); channel.attach(); @@ -3083,12 +3085,12 @@ public void presence_enter_mismatched_clientid() throws AblyException { @Test public void presence_enterclient_null_clientid() throws AblyException { String channelName = "presence_enterclient_null_clientid_" + testParams.name; - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; try { /* init ably for token */ ClientOptions optsForToken = createOptions(testVars.keys[0].keyStr); - final AblyRest ablyForToken = new AblyRest(optsForToken); + final PubSubHttpClient ablyForToken = HttpClientFactory.create(optsForToken); /* get first token */ Auth.TokenParams tokenParams = new Auth.TokenParams(); @@ -3099,7 +3101,7 @@ public void presence_enterclient_null_clientid() throws AblyException { ClientOptions opts = createOptions(token.token); opts.clientId = testClientId1; - ably = new AblyRealtime(opts); + ably = RealtimeClientFactory.create(opts); Channel channel = ably.channels.get(channelName); channel.attach(); @@ -3141,7 +3143,7 @@ public void presence_enterclient_null_clientid() throws AblyException { */ @Test public void protocol_enter_message_format() throws AblyException, InterruptedException { - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; try { final ArrayList sentPresence = new ArrayList<>(); @@ -3165,7 +3167,7 @@ public boolean matches(ProtocolMessage message) { fillInOptions(opts); opts.clientId = testClientId1; opts.transportFactory = mockTransport; - ably = new AblyRealtime(opts); + ably = RealtimeClientFactory.create(opts); Channel channel = ably.channels.get("protocol_enter_message_format_" + testParams.name); /* using testClientId1 */ @@ -3206,7 +3208,7 @@ public boolean matches(ProtocolMessage message) { */ @Test public void protocol_enterclient_message_format() throws AblyException, InterruptedException { - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; try { final ArrayList sentPresence = new ArrayList<>(); @@ -3229,7 +3231,7 @@ public boolean matches(ProtocolMessage message) { DebugOptions opts = new DebugOptions(testVars.keys[0].keyStr); fillInOptions(opts); opts.transportFactory = mockTransport; - ably = new AblyRealtime(opts); + ably = RealtimeClientFactory.create(opts); Channel channel = ably.channels.get("protocol_enterclient_message_format_" + testParams.name); /* using testClientId2 */ @@ -3268,13 +3270,13 @@ public boolean matches(ProtocolMessage message) { */ @Test public void presence_encoding() throws AblyException, InterruptedException { - AblyRealtime ably1 = null, ably2 = null; + PubSubRealtimeClient ably1 = null, ably2 = null; try { /* Set up two connections: one for entering, one for listening */ final String channelName = "presence_encoding" + testParams.name; ClientOptions opts = createOptions(testVars.keys[0].keyStr); - ably1 = new AblyRealtime(opts); - ably2 = new AblyRealtime(opts); + ably1 = RealtimeClientFactory.create(opts); + ably2 = RealtimeClientFactory.create(opts); Channel channel1 = ably1.channels.get(channelName); Channel channel2 = ably2.channels.get(channelName); @@ -3338,12 +3340,12 @@ public void onPresenceMessage(PresenceMessage message) { */ @Test public void presence_get() throws AblyException, InterruptedException { - AblyRealtime ably1 = null, ably2 = null; + PubSubRealtimeClient ably1 = null, ably2 = null; try { /* Set up two connections: one for entering, one for listening */ final String channelName = "presence_get" + testParams.name; ClientOptions opts = createOptions(testVars.keys[0].keyStr); - ably1 = new AblyRealtime(opts); + ably1 = RealtimeClientFactory.create(opts); Channel channel1 = ably1.channels.get(channelName); CompletionWaiter completionWaiter = new CompletionWaiter(); @@ -3352,7 +3354,7 @@ public void presence_get() throws AblyException, InterruptedException { completionWaiter.waitFor(2); opts.autoConnect = false; - ably2 = new AblyRealtime(opts); + ably2 = RealtimeClientFactory.create(opts); Channel channel2 = ably2.channels.get(channelName); PresenceWaiter waiter2 = new PresenceWaiter(channel2); @@ -3433,7 +3435,7 @@ public void checkMembersWithChannelPresence(Channel testChannel) throws AblyExce @Test public void test_consistent_presence_for_members() { - AblyRealtime clientAbly1 = null; + PubSubRealtimeClient clientAbly1 = null; TestChannel testChannel = new TestChannel(); try { /* subscribe for presence events in the anonymous connection */ @@ -3444,7 +3446,7 @@ public void test_consistent_presence_for_members() { clientId = testClientId1; }}; fillInOptions(client1Opts); - clientAbly1 = new AblyRealtime(client1Opts); + clientAbly1 = RealtimeClientFactory.create(client1Opts); (new ConnectionWaiter(clientAbly1.connection)).waitFor(ConnectionState.connected); assertEquals("Verify connected state reached", clientAbly1.connection.state, ConnectionState.connected); @@ -3482,7 +3484,7 @@ public void test_consistent_presence_for_members() { } /** - * Authenticate using wildcard token, initialize AblyRealtime so clientId is not known a priori, + * Authenticate using wildcard token, initialize PubSubRealtimeClient so clientId is not known a priori, * call enter() without attaching first, start connection * * Expect NACK from the server because client is unidentified @@ -3491,10 +3493,10 @@ public void test_consistent_presence_for_members() { */ @Test public void enter_before_clientid_is_known() throws AblyException { - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; try { - ClientOptions restOpts = createOptions(testVars.keys[0].keyStr); - AblyRest ablyForToken = new AblyRest(restOpts); + ClientOptions httpOpts = createOptions(testVars.keys[0].keyStr); + PubSubHttpClient ablyForToken = HttpClientFactory.create(httpOpts); /* Initialize connection so clientId is not known before actual connection */ Auth.TokenParams tokenParams = new Auth.TokenParams(); @@ -3509,7 +3511,7 @@ public void enter_before_clientid_is_known() throws AblyException { opts.defaultTokenParams.clientId = "*"; opts.token = token.token; opts.autoConnect = false; - ably = new AblyRealtime(opts); + ably = RealtimeClientFactory.create(opts); /* enter without attaching first */ Channel channel = ably.channels.get("enter_before_clientid_is_known"+testParams.name); diff --git a/lib/src/test/java/io/ably/lib/test/realtime/RealtimeReauthTest.java b/lib/src/test/java/io/ably/pubsub/test/realtime/RealtimeReauthTest.java similarity index 85% rename from lib/src/test/java/io/ably/lib/test/realtime/RealtimeReauthTest.java rename to lib/src/test/java/io/ably/pubsub/test/realtime/RealtimeReauthTest.java index 4a7c14386..2120a09eb 100644 --- a/lib/src/test/java/io/ably/lib/test/realtime/RealtimeReauthTest.java +++ b/lib/src/test/java/io/ably/pubsub/test/realtime/RealtimeReauthTest.java @@ -1,22 +1,24 @@ -package io.ably.lib.test.realtime; - -import io.ably.lib.realtime.AblyRealtime; -import io.ably.lib.realtime.Channel; -import io.ably.lib.realtime.ChannelState; -import io.ably.lib.realtime.ConnectionEvent; -import io.ably.lib.realtime.ConnectionState; -import io.ably.lib.realtime.ConnectionStateListener; -import io.ably.lib.rest.AblyRest; -import io.ably.lib.rest.Auth; -import io.ably.lib.rest.Auth.TokenCallback; -import io.ably.lib.rest.Auth.TokenDetails; -import io.ably.lib.rest.Auth.TokenParams; -import io.ably.lib.test.common.Helpers; -import io.ably.lib.test.common.ParameterizedTest; -import io.ably.lib.types.AblyException; -import io.ably.lib.types.Capability; -import io.ably.lib.types.ClientOptions; -import io.ably.lib.types.ErrorInfo; +package io.ably.pubsub.test.realtime; + +import io.ably.pubsub.realtime.PubSubRealtimeClient; +import io.ably.pubsub.realtime.RealtimeClientFactory; +import io.ably.pubsub.realtime.Channel; +import io.ably.pubsub.realtime.ChannelState; +import io.ably.pubsub.realtime.ConnectionEvent; +import io.ably.pubsub.realtime.ConnectionState; +import io.ably.pubsub.realtime.ConnectionStateListener; +import io.ably.pubsub.http.HttpClientFactory; +import io.ably.pubsub.http.PubSubHttpClient; +import io.ably.pubsub.http.Auth; +import io.ably.pubsub.http.Auth.TokenCallback; +import io.ably.pubsub.http.Auth.TokenDetails; +import io.ably.pubsub.http.Auth.TokenParams; +import io.ably.pubsub.test.common.Helpers; +import io.ably.pubsub.test.common.ParameterizedTest; +import io.ably.pubsub.types.AblyException; +import io.ably.pubsub.types.Capability; +import io.ably.pubsub.types.ClientOptions; +import io.ably.pubsub.types.ErrorInfo; import org.junit.Rule; import org.junit.Test; import org.junit.rules.Timeout; @@ -54,7 +56,7 @@ public void reauth_tokenDetails() { try { /* init ably for token */ ClientOptions optsForToken = createOptions(testVars.keys[0].keyStr); - final AblyRest ablyForToken = new AblyRest(optsForToken); + final PubSubHttpClient ablyForToken = HttpClientFactory.create(optsForToken); /* get first token */ Auth.TokenParams tokenParams = new Auth.TokenParams(); @@ -70,15 +72,15 @@ public void reauth_tokenDetails() { ClientOptions opts = createOptions(); opts.clientId = testClientId; opts.tokenDetails = firstToken; - AblyRealtime ablyRealtime = new AblyRealtime(opts); + PubSubRealtimeClient realtimeClient = RealtimeClientFactory.create(opts); /* wait for connected state */ - Helpers.ConnectionWaiter connectionWaiter = new Helpers.ConnectionWaiter(ablyRealtime.connection); + Helpers.ConnectionWaiter connectionWaiter = new Helpers.ConnectionWaiter(realtimeClient.connection); connectionWaiter.waitFor(ConnectionState.connected); - assertEquals("Verify connected state is reached", ConnectionState.connected, ablyRealtime.connection.state); + assertEquals("Verify connected state is reached", ConnectionState.connected, realtimeClient.connection.state); /* create a channel and check can't attach */ - Channel channel = ablyRealtime.channels.get(rightChannel); + Channel channel = realtimeClient.channels.get(rightChannel); Helpers.CompletionWaiter waiter = new Helpers.CompletionWaiter(); channel.attach(waiter); ErrorInfo error = waiter.waitFor(); @@ -101,7 +103,7 @@ public void reauth_tokenDetails() { Auth.AuthOptions authOptions = new Auth.AuthOptions(); authOptions.key = testVars.keys[0].keyStr; authOptions.tokenDetails = secondToken; - Auth.TokenDetails reauthTokenDetails = ablyRealtime.auth.authorize(null, authOptions); + Auth.TokenDetails reauthTokenDetails = realtimeClient.auth.authorize(null, authOptions); assertNotNull("Expected token value", reauthTokenDetails.token); /* re-attach to the channel */ @@ -114,7 +116,7 @@ public void reauth_tokenDetails() { /* Verify that the connection never disconnected (0.9 in-place authorization) */ assertTrue("Expected in-place authorization", connectionWaiter.getCount(ConnectionState.connecting) == 0); - ablyRealtime.close(); + realtimeClient.close(); } catch (AblyException e) { e.printStackTrace(); fail(); @@ -138,7 +140,7 @@ public void reauth_downgrade() { try { /* init ably for token */ ClientOptions optsForToken = createOptions(testVars.keys[0].keyStr); - final AblyRest ablyForToken = new AblyRest(optsForToken); + final PubSubHttpClient ablyForToken = HttpClientFactory.create(optsForToken); /* get first (good) token */ Auth.TokenParams tokenParams = new Auth.TokenParams(); @@ -154,15 +156,15 @@ public void reauth_downgrade() { ClientOptions opts = createOptions(); opts.clientId = testClientId; opts.tokenDetails = firstToken; - AblyRealtime ablyRealtime = new AblyRealtime(opts); + PubSubRealtimeClient realtimeClient = RealtimeClientFactory.create(opts); /* wait for connected state */ - Helpers.ConnectionWaiter connectionWaiter = new Helpers.ConnectionWaiter(ablyRealtime.connection); + Helpers.ConnectionWaiter connectionWaiter = new Helpers.ConnectionWaiter(realtimeClient.connection); connectionWaiter.waitFor(ConnectionState.connected); - assertEquals("Verify connected state is reached", ConnectionState.connected, ablyRealtime.connection.state); + assertEquals("Verify connected state is reached", ConnectionState.connected, realtimeClient.connection.state); /* create a channel and check attached */ - Channel channel = ablyRealtime.channels.get(rightChannel); + Channel channel = realtimeClient.channels.get(rightChannel); Helpers.ChannelWaiter waiter = new Helpers.ChannelWaiter(channel); channel.attach(); /* verify onSuccess callback gets called */ @@ -182,7 +184,7 @@ public void reauth_downgrade() { connectionWaiter.reset(); Auth.AuthOptions authOptions = new Auth.AuthOptions(); authOptions.tokenDetails = secondToken; - Auth.TokenDetails reauthTokenDetails = ablyRealtime.auth.authorize(null, authOptions); + Auth.TokenDetails reauthTokenDetails = realtimeClient.auth.authorize(null, authOptions); assertNotNull("Expected token value", reauthTokenDetails.token); /* Check that the channel moves to failed state within 2s, and that @@ -193,7 +195,7 @@ public void reauth_downgrade() { assertEquals("Verify error code", err.code, 40160); assertTrue("Expected channel to fail quickly", System.currentTimeMillis() - before < 2000); - ablyRealtime.close(); + realtimeClient.close(); } catch (AblyException e) { e.printStackTrace(); fail(); @@ -215,7 +217,7 @@ public void reauth_fail() { try { /* init ably for token */ ClientOptions optsForToken = createOptions(testVars.keys[0].keyStr); - final AblyRest ablyForToken = new AblyRest(optsForToken); + final PubSubHttpClient ablyForToken = HttpClientFactory.create(optsForToken); /* get first (good) token */ Auth.TokenParams tokenParams = new Auth.TokenParams(); @@ -230,15 +232,15 @@ public void reauth_fail() { ClientOptions opts = createOptions(); opts.clientId = testClientId; opts.tokenDetails = firstToken; - AblyRealtime ablyRealtime = new AblyRealtime(opts); + PubSubRealtimeClient realtimeClient = RealtimeClientFactory.create(opts); /* wait for connected state */ - Helpers.ConnectionWaiter connectionWaiter = new Helpers.ConnectionWaiter(ablyRealtime.connection); + Helpers.ConnectionWaiter connectionWaiter = new Helpers.ConnectionWaiter(realtimeClient.connection); connectionWaiter.waitFor(ConnectionState.connected); - assertEquals("Verify connected state is reached", ConnectionState.connected, ablyRealtime.connection.state); + assertEquals("Verify connected state is reached", ConnectionState.connected, realtimeClient.connection.state); /* create a channel and check attached */ - Channel channel = ablyRealtime.channels.get(rightChannel); + Channel channel = realtimeClient.channels.get(rightChannel); Helpers.ChannelWaiter waiter = new Helpers.ChannelWaiter(channel); channel.attach(); /* verify onSuccess callback gets called */ @@ -258,11 +260,11 @@ public void reauth_fail() { Auth.AuthOptions authOptions = new Auth.AuthOptions(); authOptions.tokenDetails = secondToken; try { - Auth.TokenDetails reauthTokenDetails = ablyRealtime.auth.authorize(null, authOptions); + Auth.TokenDetails reauthTokenDetails = realtimeClient.auth.authorize(null, authOptions); assertFalse("Expecting exception", true); System.out.println("Authorize failed to throw an exception"); } catch (AblyException e) { - assertEquals("Expecting failed", ConnectionState.failed, ablyRealtime.connection.state); + assertEquals("Expecting failed", ConnectionState.failed, realtimeClient.connection.state); System.out.println("Got failed connection"); } @@ -277,12 +279,12 @@ public void reauth_fail() { connectionWaiter.reset(); authOptions = new Auth.AuthOptions(); authOptions.tokenDetails = firstToken; - Auth.TokenDetails reauthTokenDetails = ablyRealtime.auth.authorize(null, authOptions); + Auth.TokenDetails reauthTokenDetails = realtimeClient.auth.authorize(null, authOptions); assertNotNull("Expected token value", reauthTokenDetails.token); connectionWaiter.waitFor(ConnectionState.connected); - assertEquals("Verify connected state is reached", ConnectionState.connected, ablyRealtime.connection.state); + assertEquals("Verify connected state is reached", ConnectionState.connected, realtimeClient.connection.state); - ablyRealtime.close(); + realtimeClient.close(); } catch (AblyException e) { e.printStackTrace(); fail(); @@ -302,7 +304,7 @@ public void reauth_failure_test() { /* init ably for token */ ClientOptions optsForToken = createOptions(testVars.keys[0].keyStr); - final AblyRest ablyForToken = new AblyRest(optsForToken); + final PubSubHttpClient ablyForToken = HttpClientFactory.create(optsForToken); /* get first token */ Auth.TokenParams tokenParams = new Auth.TokenParams(); @@ -314,9 +316,9 @@ public void reauth_failure_test() { ClientOptions opts = createOptions(); opts.clientId = testClientId; opts.tokenDetails = firstToken; - AblyRealtime ablyRealtime = new AblyRealtime(opts); + PubSubRealtimeClient realtimeClient = RealtimeClientFactory.create(opts); - ablyRealtime.connection.on(new ConnectionStateListener() { + realtimeClient.connection.on(new ConnectionStateListener() { @Override public void onConnectionStateChanged(ConnectionStateChange state) { synchronized (stateChangeHistory) { @@ -328,12 +330,12 @@ public void onConnectionStateChanged(ConnectionStateChange state) { /* wait for connected state */ synchronized (stateChangeHistory) { - while (ablyRealtime.connection.state != ConnectionState.connected) { + while (realtimeClient.connection.state != ConnectionState.connected) { try { stateChangeHistory.wait(); } catch (InterruptedException e) {} } } - assertEquals("Verify connected state is reached", ConnectionState.connected, ablyRealtime.connection.state); + assertEquals("Verify connected state is reached", ConnectionState.connected, realtimeClient.connection.state); int stateChangeCount = stateChangeHistory.size(); @@ -343,7 +345,7 @@ public void onConnectionStateChanged(ConnectionStateChange state) { authOptions.key = testVars.keys[0].keyStr; authOptions.authUrl = "https://nonexistent-domain-abcdef.com"; try { - ablyRealtime.auth.authorize(null, authOptions); + realtimeClient.auth.authorize(null, authOptions); // should not succeed fail(); } @@ -363,7 +365,7 @@ public void onConnectionStateChanged(ConnectionStateChange state) { assertEquals("Verify authentication failure error code", lastChange.reason.code, 80019); } - ablyRealtime.close(); + realtimeClient.close(); } catch (AblyException e) { e.printStackTrace(); fail(); @@ -381,7 +383,7 @@ public void onConnectionStateChanged(ConnectionStateChange state) { public void reauth_token_expire_inplace_reauth() { try { ClientOptions optsForToken = createOptions(testVars.keys[0].keyStr); - final AblyRest ablyForToken = new AblyRest(optsForToken); + final PubSubHttpClient ablyForToken = HttpClientFactory.create(optsForToken); /* Server will send reauth message 30 seconds before token expiration time i.e. in 4 seconds */ TokenDetails tokenDetails = ablyForToken.auth.requestToken(new TokenParams() {{ ttl = 34000L; }}, null); assertNotNull("Expected token value", tokenDetails.token); @@ -405,7 +407,7 @@ public Object getTokenRequest(TokenParams params) throws AblyException { return ablyForToken.auth.requestToken(params, null); } }; - AblyRealtime ably = new AblyRealtime(opts); + PubSubRealtimeClient ably = RealtimeClientFactory.create(opts); /* Test UPDATE event delivery */ ably.connection.on(ConnectionEvent.update, new ConnectionStateListener() { @@ -464,7 +466,7 @@ public void reauth_key_expire_inplace_reauth() { opts.clientId = "testClientId"; opts.useTokenAuth = true; opts.defaultTokenParams.ttl = 34000L; - AblyRealtime ably = new AblyRealtime(opts); + PubSubRealtimeClient ably = RealtimeClientFactory.create(opts); /* Test UPDATE event delivery */ ably.connection.on(ConnectionEvent.update, new ConnectionStateListener() { diff --git a/lib/src/test/java/io/ably/lib/test/realtime/RealtimeRecoverTest.java b/lib/src/test/java/io/ably/pubsub/test/realtime/RealtimeRecoverTest.java similarity index 90% rename from lib/src/test/java/io/ably/lib/test/realtime/RealtimeRecoverTest.java rename to lib/src/test/java/io/ably/pubsub/test/realtime/RealtimeRecoverTest.java index 59d08c2d4..77d4dc99e 100644 --- a/lib/src/test/java/io/ably/lib/test/realtime/RealtimeRecoverTest.java +++ b/lib/src/test/java/io/ably/pubsub/test/realtime/RealtimeRecoverTest.java @@ -1,22 +1,23 @@ -package io.ably.lib.test.realtime; - -import io.ably.lib.debug.DebugOptions; -import io.ably.lib.realtime.AblyRealtime; -import io.ably.lib.realtime.Channel; -import io.ably.lib.realtime.ChannelState; -import io.ably.lib.realtime.ConnectionState; -import io.ably.lib.test.common.Helpers.ChannelWaiter; -import io.ably.lib.test.common.Helpers.CompletionSet; -import io.ably.lib.test.common.Helpers.ConnectionWaiter; -import io.ably.lib.test.common.Helpers.MessageWaiter; -import io.ably.lib.test.common.ParameterizedTest; -import io.ably.lib.transport.ConnectionManager; -import io.ably.lib.transport.ITransport; -import io.ably.lib.transport.WebSocketTransport; -import io.ably.lib.types.AblyException; -import io.ably.lib.types.ClientOptions; -import io.ably.lib.types.ErrorInfo; -import io.ably.lib.types.ProtocolMessage; +package io.ably.pubsub.test.realtime; + +import io.ably.pubsub.debug.DebugOptions; +import io.ably.pubsub.realtime.PubSubRealtimeClient; +import io.ably.pubsub.realtime.RealtimeClientFactory; +import io.ably.pubsub.realtime.Channel; +import io.ably.pubsub.realtime.ChannelState; +import io.ably.pubsub.realtime.ConnectionState; +import io.ably.pubsub.test.common.Helpers.ChannelWaiter; +import io.ably.pubsub.test.common.Helpers.CompletionSet; +import io.ably.pubsub.test.common.Helpers.ConnectionWaiter; +import io.ably.pubsub.test.common.Helpers.MessageWaiter; +import io.ably.pubsub.test.common.ParameterizedTest; +import io.ably.pubsub.transport.ConnectionManager; +import io.ably.pubsub.transport.ITransport; +import io.ably.pubsub.transport.WebSocketTransport; +import io.ably.pubsub.types.AblyException; +import io.ably.pubsub.types.ClientOptions; +import io.ably.pubsub.types.ErrorInfo; +import io.ably.pubsub.types.ProtocolMessage; import org.junit.Ignore; import org.junit.Test; @@ -44,14 +45,14 @@ public class RealtimeRecoverTest extends ParameterizedTest { @Ignore("FIXME: fix exception") @Test public void recover_disconnected() { - AblyRealtime ablyRx = null, ablyTx = null, ablyRxRecover = null; + PubSubRealtimeClient ablyRx = null, ablyTx = null, ablyRxRecover = null; String channelName = "recover_disconnected"; int messageCount = 5; long delay = 200; try { ClientOptions opts = createOptions(testVars.keys[0].keyStr); - ablyRx = new AblyRealtime(opts); - ablyTx = new AblyRealtime(opts); + ablyRx = RealtimeClientFactory.create(opts); + ablyTx = RealtimeClientFactory.create(opts); /* create and attach channel to send on */ final Channel channelTx = ablyTx.channels.get(channelName); @@ -87,7 +88,7 @@ public void recover_disconnected() { * NOTE this depends on knowledge of the internal structure * of the library, to simulate a dropped transport without * causing the connection itself to be disposed */ - String recoverConnectionKey = ablyRx.connection.recoveryKey; + String recoverConnectionKey = ablyRx.connection.createRecoveryKey(); ablyRx.connection.connectionManager.requestState(ConnectionState.failed); /* wait */ @@ -107,7 +108,7 @@ public void recover_disconnected() { /* establish a new rx connection with recover string, and wait for connection */ ClientOptions recoverOpts = createOptions(testVars.keys[0].keyStr); recoverOpts.recover = recoverConnectionKey; - ablyRxRecover = new AblyRealtime(recoverOpts); + ablyRxRecover = RealtimeClientFactory.create(recoverOpts); (new ConnectionWaiter(ablyRxRecover.connection)).waitFor(ConnectionState.connected); /* subscribe to channel */ @@ -144,14 +145,14 @@ public void recover_disconnected() { @Ignore("FIXME: fix exception") @Test public void recover_implicit_connect() { - AblyRealtime ablyRx = null, ablyTx = null, ablyRxRecover = null; + PubSubRealtimeClient ablyRx = null, ablyTx = null, ablyRxRecover = null; String channelName = "recover_implicit_connect"; int messageCount = 5; long delay = 200; try { ClientOptions opts = createOptions(testVars.keys[0].keyStr); - ablyRx = new AblyRealtime(opts); - ablyTx = new AblyRealtime(opts); + ablyRx = RealtimeClientFactory.create(opts); + ablyTx = RealtimeClientFactory.create(opts); /* create and attach channel to send on */ final Channel channelTx = ablyTx.channels.get(channelName); @@ -187,7 +188,7 @@ public void recover_implicit_connect() { * NOTE this depends on knowledge of the internal structure * of the library, to simulate a dropped transport without * causing the connection itself to be disposed */ - String recoverConnectionKey = ablyRx.connection.recoveryKey; + String recoverConnectionKey = ablyRx.connection.createRecoveryKey(); ablyRx.connection.connectionManager.requestState(ConnectionState.failed); /* wait */ @@ -207,7 +208,7 @@ public void recover_implicit_connect() { /* establish a new rx connection with recover string, and wait for connection */ ClientOptions recoverOpts = createOptions(testVars.keys[0].keyStr); recoverOpts.recover = recoverConnectionKey; - ablyRxRecover = new AblyRealtime(recoverOpts); + ablyRxRecover = RealtimeClientFactory.create(recoverOpts); /* subscribe to channel */ final Channel channelRxRecover = ablyRxRecover.channels.get(channelName); @@ -239,14 +240,14 @@ public void recover_implicit_connect() { @Ignore("FIXME: fix exception") @Test public void recover_verify_publish() { - AblyRealtime ablyRx = null, ablyTx = null; + PubSubRealtimeClient ablyRx = null, ablyTx = null; String channelName = "recover_verify_publish"; int messageCount = 5; long delay = 200; try { ClientOptions opts = createOptions(testVars.keys[0].keyStr); - ablyRx = new AblyRealtime(opts); - ablyTx = new AblyRealtime(opts); + ablyRx = RealtimeClientFactory.create(opts); + ablyTx = RealtimeClientFactory.create(opts); /* create and attach channel to send on */ final Channel channelTx = ablyTx.channels.get(channelName); @@ -336,7 +337,7 @@ public void recover_verify_publish() { */ @Test public void recover_transport_send_exception() { - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; final String channelName = "recover_transport_send_exception"; try { MockWebsocketFactory mockTransport = new MockWebsocketFactory(); @@ -348,7 +349,7 @@ public void recover_transport_send_exception() { opts.transportFactory = mockTransport; opts.autoConnect = false; - ably = new AblyRealtime(opts); + ably = RealtimeClientFactory.create(opts); ConnectionWaiter connWaiter = new ConnectionWaiter(ably.connection); ably.connection.connect(); connWaiter.waitFor(ConnectionState.connected); diff --git a/lib/src/test/java/io/ably/lib/test/realtime/RealtimeResumeTest.java b/lib/src/test/java/io/ably/pubsub/test/realtime/RealtimeResumeTest.java similarity index 94% rename from lib/src/test/java/io/ably/lib/test/realtime/RealtimeResumeTest.java rename to lib/src/test/java/io/ably/pubsub/test/realtime/RealtimeResumeTest.java index eceb070cb..9987c26bc 100644 --- a/lib/src/test/java/io/ably/lib/test/realtime/RealtimeResumeTest.java +++ b/lib/src/test/java/io/ably/pubsub/test/realtime/RealtimeResumeTest.java @@ -1,24 +1,25 @@ -package io.ably.lib.test.realtime; - -import io.ably.lib.debug.DebugOptions; -import io.ably.lib.realtime.AblyRealtime; -import io.ably.lib.realtime.Channel; -import io.ably.lib.realtime.ChannelState; -import io.ably.lib.realtime.ConnectionState; -import io.ably.lib.test.common.Helpers; -import io.ably.lib.test.common.Helpers.ChannelWaiter; -import io.ably.lib.test.common.Helpers.CompletionSet; -import io.ably.lib.test.common.Helpers.ConnectionWaiter; -import io.ably.lib.test.common.Helpers.MessageWaiter; -import io.ably.lib.test.common.ParameterizedTest; -import io.ably.lib.test.util.MockWebsocketFactory; -import io.ably.lib.types.AblyException; -import io.ably.lib.types.ClientOptions; -import io.ably.lib.types.ErrorInfo; -import io.ably.lib.types.Message; -import io.ably.lib.types.PresenceMessage; -import io.ably.lib.types.ProtocolMessage; -import io.ably.lib.util.Log; +package io.ably.pubsub.test.realtime; + +import io.ably.pubsub.debug.DebugOptions; +import io.ably.pubsub.realtime.PubSubRealtimeClient; +import io.ably.pubsub.realtime.RealtimeClientFactory; +import io.ably.pubsub.realtime.Channel; +import io.ably.pubsub.realtime.ChannelState; +import io.ably.pubsub.realtime.ConnectionState; +import io.ably.pubsub.test.common.Helpers; +import io.ably.pubsub.test.common.Helpers.ChannelWaiter; +import io.ably.pubsub.test.common.Helpers.CompletionSet; +import io.ably.pubsub.test.common.Helpers.ConnectionWaiter; +import io.ably.pubsub.test.common.Helpers.MessageWaiter; +import io.ably.pubsub.test.common.ParameterizedTest; +import io.ably.pubsub.test.util.MockWebsocketFactory; +import io.ably.pubsub.types.AblyException; +import io.ably.pubsub.types.ClientOptions; +import io.ably.pubsub.types.ErrorInfo; +import io.ably.pubsub.types.Message; +import io.ably.pubsub.types.PresenceMessage; +import io.ably.pubsub.types.ProtocolMessage; +import io.ably.pubsub.util.Log; import org.junit.Ignore; import org.junit.Rule; @@ -49,11 +50,11 @@ public class RealtimeResumeTest extends ParameterizedTest { */ @Test public void resume_none() { - AblyRealtime ably = null; + PubSubRealtimeClient ably = null; String channelName = "resume_none"; try { ClientOptions opts = createOptions(testVars.keys[0].keyStr); - ably = new AblyRealtime(opts); + ably = RealtimeClientFactory.create(opts); ConnectionWaiter connectionWaiter = new ConnectionWaiter(ably.connection); connectionWaiter.waitFor(ConnectionState.connected); @@ -100,15 +101,15 @@ public void resume_none() { @Ignore("FIXME: fix exception") @Test public void resume_simple() { - AblyRealtime ablyTx = null; - AblyRealtime ablyRx = null; + PubSubRealtimeClient ablyTx = null; + PubSubRealtimeClient ablyRx = null; String channelName = "resume_simple"; int messageCount = 5; long delay = 200; try { ClientOptions opts = createOptions(testVars.keys[0].keyStr); - ablyRx = new AblyRealtime(opts); - ablyTx = new AblyRealtime(opts); + ablyRx = RealtimeClientFactory.create(opts); + ablyTx = RealtimeClientFactory.create(opts); /* create and attach channel to send on */ final Channel channelTx = ablyTx.channels.get(channelName); @@ -191,15 +192,15 @@ public void resume_simple() { @Ignore("FIXME: fix exception") @Test public void resume_disconnected() { - AblyRealtime ablyTx = null; - AblyRealtime ablyRx = null; + PubSubRealtimeClient ablyTx = null; + PubSubRealtimeClient ablyRx = null; String channelName = "resume_disconnected"; int messageCount = 5; long delay = 200; try { ClientOptions opts = createOptions(testVars.keys[0].keyStr); - ablyRx = new AblyRealtime(opts); - ablyTx = new AblyRealtime(opts); + ablyRx = RealtimeClientFactory.create(opts); + ablyTx = RealtimeClientFactory.create(opts); /* create and attach channel to send on */ final Channel channelTx = ablyTx.channels.get(channelName); @@ -277,15 +278,15 @@ public void resume_disconnected() { @Ignore("FIXME: fix exception") @Test public void resume_multiple_channel() { - AblyRealtime ablyTx = null; - AblyRealtime ablyRx = null; + PubSubRealtimeClient ablyTx = null; + PubSubRealtimeClient ablyRx = null; String channelName = "resume_multiple_channel"; int messageCount = 5; long delay = 200; try { ClientOptions opts = createOptions(testVars.keys[0].keyStr); - ablyRx = new AblyRealtime(opts); - ablyTx = new AblyRealtime(opts); + ablyRx = RealtimeClientFactory.create(opts); + ablyTx = RealtimeClientFactory.create(opts); /* create and attach channels to send on */ final Channel channelTx1 = ablyTx.channels.get(channelName + "_1"); @@ -380,15 +381,15 @@ public void resume_multiple_channel() { @Ignore("FIXME: fix exception") @Test public void resume_multiple_interval() { - AblyRealtime ablyTx = null; - AblyRealtime ablyRx = null; + PubSubRealtimeClient ablyTx = null; + PubSubRealtimeClient ablyRx = null; String channelName = "resume_multiple_interval"; int messageCount = 5; long delay = 200; try { ClientOptions opts = createOptions(testVars.keys[0].keyStr); - ablyRx = new AblyRealtime(opts); - ablyTx = new AblyRealtime(opts); + ablyRx = RealtimeClientFactory.create(opts); + ablyTx = RealtimeClientFactory.create(opts); /* create and attach channel to send on */ final Channel channelTx = ablyTx.channels.get(channelName); @@ -469,15 +470,15 @@ public void resume_multiple_interval() { @Ignore("FIXME: fix exception") @Test public void resume_verify_publish() { - AblyRealtime ablyTx = null; - AblyRealtime ablyRx = null; + PubSubRealtimeClient ablyTx = null; + PubSubRealtimeClient ablyRx = null; String channelName = "resume_verify_publish"; int messageCount = 5; long delay = 200; try { ClientOptions opts = createOptions(testVars.keys[0].keyStr); - ablyRx = new AblyRealtime(opts); - ablyTx = new AblyRealtime(opts); + ablyRx = RealtimeClientFactory.create(opts); + ablyTx = RealtimeClientFactory.create(opts); /* create and attach channel to send on */ final Channel channelTx = ablyTx.channels.get(channelName); @@ -569,15 +570,15 @@ public void resume_verify_publish() { */ @Test public void resume_publish_queue() { - AblyRealtime receiver = null; - AblyRealtime sender = null; + PubSubRealtimeClient receiver = null; + PubSubRealtimeClient sender = null; String channelName = "resume_publish_queue"; int messageCount = 3; long delay = 200; try { ClientOptions opts = createOptions(testVars.keys[0].keyStr); - receiver = new AblyRealtime(opts); - sender = new AblyRealtime(opts); + receiver = RealtimeClientFactory.create(opts); + sender = RealtimeClientFactory.create(opts); /* create and attach channel to send on */ final Channel senderChannel = sender.channels.get(channelName); @@ -672,7 +673,7 @@ public void resume_publish_queue() { @Test public void resume_publish_resend_pending_messages_when_resume_is_successful() { final String channelName = "resume_publish_queue"; - AblyRealtime sender = null; + PubSubRealtimeClient sender = null; try { final MockWebsocketFactory mockWebsocketFactory = new MockWebsocketFactory(); String keyStr = testVars.keys[0].keyStr; @@ -680,7 +681,7 @@ public void resume_publish_resend_pending_messages_when_resume_is_successful() { senderOptions.logLevel = Log.VERBOSE; senderOptions.queueMessages = true; senderOptions.transportFactory = mockWebsocketFactory; - sender = new AblyRealtime(senderOptions); + sender = RealtimeClientFactory.create(senderOptions); (new ConnectionWaiter(sender.connection)).waitFor(ConnectionState.connected); final Channel senderChannel = sender.channels.get(channelName); @@ -790,7 +791,7 @@ public void resume_publish_resend_pending_messages_when_resume_failed() throws A options.logLevel = Log.VERBOSE; options.realtimeRequestTimeout = 2000L; options.transportFactory = mockWebsocketFactory; - try(AblyRealtime ably = new AblyRealtime(options)) { + try(PubSubRealtimeClient ably = RealtimeClientFactory.create(options)) { final long newTtl = 1000L; final long newIdleInterval = 1000L; @@ -897,7 +898,7 @@ public void resume_publish_reenter_when_resume_failed() throws AblyException { options.realtimeRequestTimeout = 2000L; options.transportFactory = mockWebsocketFactory; - try(AblyRealtime ably = new AblyRealtime(options)) { + try(PubSubRealtimeClient ably = RealtimeClientFactory.create(options)) { ConnectionWaiter connectionWaiter = new ConnectionWaiter(ably.connection); connectionWaiter.waitFor(ConnectionState.connected); @@ -1013,16 +1014,16 @@ public void resume_publish_reenter_when_resume_failed() throws AblyException { @Test public void resume_rewind_1 () { - AblyRealtime receiver1 = null; - AblyRealtime receiver2 = null; - AblyRealtime sender = null; + PubSubRealtimeClient receiver1 = null; + PubSubRealtimeClient receiver2 = null; + PubSubRealtimeClient sender = null; final String testMessage = "{ foo: \"bar\", count: 1, status: \"active\" }"; String testName = "resume_rewind_1"; try { ClientOptions common_opts = createOptions(testVars.keys[0].keyStr); - sender = new AblyRealtime(common_opts); - receiver1 = new AblyRealtime(common_opts); + sender = RealtimeClientFactory.create(common_opts); + receiver1 = RealtimeClientFactory.create(common_opts); DebugOptions receiver2_opts = createOptions(testVars.keys[0].keyStr); receiver2_opts.protocolListener = new DebugOptions.RawProtocolListener() { @@ -1039,7 +1040,7 @@ public void onRawMessageSend(ProtocolMessage message) { @Override public void onRawMessageRecv(ProtocolMessage message) {} }; - receiver2 = new AblyRealtime(receiver2_opts); + receiver2 = RealtimeClientFactory.create(receiver2_opts); Channel receiver1_channel = receiver1.channels.get("[?rewind=1]" + testName); diff --git a/lib/src/test/java/io/ably/lib/test/realtime/RealtimeSuite.java b/lib/src/test/java/io/ably/pubsub/test/realtime/RealtimeSuite.java similarity index 94% rename from lib/src/test/java/io/ably/lib/test/realtime/RealtimeSuite.java rename to lib/src/test/java/io/ably/pubsub/test/realtime/RealtimeSuite.java index 0c61d5b44..8206fa55c 100644 --- a/lib/src/test/java/io/ably/lib/test/realtime/RealtimeSuite.java +++ b/lib/src/test/java/io/ably/pubsub/test/realtime/RealtimeSuite.java @@ -1,4 +1,4 @@ -package io.ably.lib.test.realtime; +package io.ably.pubsub.test.realtime; import org.junit.AfterClass; import org.junit.BeforeClass; @@ -9,7 +9,7 @@ import org.junit.runners.Suite; import org.junit.runners.Suite.SuiteClasses; -import io.ably.lib.test.common.Setup; +import io.ably.pubsub.test.common.Setup; @RunWith(Suite.class) @SuiteClasses({ diff --git a/lib/src/test/java/io/ably/lib/test/util/AblyCommonsReader.java b/lib/src/test/java/io/ably/pubsub/test/util/AblyCommonsReader.java similarity index 97% rename from lib/src/test/java/io/ably/lib/test/util/AblyCommonsReader.java rename to lib/src/test/java/io/ably/pubsub/test/util/AblyCommonsReader.java index aa8b30f32..4cfed00c1 100644 --- a/lib/src/test/java/io/ably/lib/test/util/AblyCommonsReader.java +++ b/lib/src/test/java/io/ably/pubsub/test/util/AblyCommonsReader.java @@ -1,4 +1,4 @@ -package io.ably.lib.test.util; +package io.ably.pubsub.test.util; import com.google.gson.Gson; import com.google.gson.JsonObject; diff --git a/lib/src/test/java/io/ably/lib/test/util/EmptyPlatformAgentProvider.java b/lib/src/test/java/io/ably/pubsub/test/util/EmptyPlatformAgentProvider.java similarity index 65% rename from lib/src/test/java/io/ably/lib/test/util/EmptyPlatformAgentProvider.java rename to lib/src/test/java/io/ably/pubsub/test/util/EmptyPlatformAgentProvider.java index fbc3ea59b..2c4e05d98 100644 --- a/lib/src/test/java/io/ably/lib/test/util/EmptyPlatformAgentProvider.java +++ b/lib/src/test/java/io/ably/pubsub/test/util/EmptyPlatformAgentProvider.java @@ -1,6 +1,6 @@ -package io.ably.lib.test.util; +package io.ably.pubsub.test.util; -import io.ably.lib.util.PlatformAgentProvider; +import io.ably.pubsub.util.PlatformAgentProvider; public class EmptyPlatformAgentProvider implements PlatformAgentProvider { @Override diff --git a/lib/src/test/java/io/ably/lib/test/util/MockWebsocketFactory.java b/lib/src/test/java/io/ably/pubsub/test/util/MockWebsocketFactory.java similarity index 96% rename from lib/src/test/java/io/ably/lib/test/util/MockWebsocketFactory.java rename to lib/src/test/java/io/ably/pubsub/test/util/MockWebsocketFactory.java index 15a4cbfad..6a0041b2a 100644 --- a/lib/src/test/java/io/ably/lib/test/util/MockWebsocketFactory.java +++ b/lib/src/test/java/io/ably/pubsub/test/util/MockWebsocketFactory.java @@ -1,17 +1,17 @@ -package io.ably.lib.test.util; +package io.ably.pubsub.test.util; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.stream.Collectors; -import io.ably.lib.transport.ConnectionManager; -import io.ably.lib.transport.ITransport; -import io.ably.lib.transport.WebSocketTransport; -import io.ably.lib.types.AblyException; -import io.ably.lib.types.ErrorInfo; -import io.ably.lib.types.PresenceMessage; -import io.ably.lib.types.ProtocolMessage; +import io.ably.pubsub.transport.ConnectionManager; +import io.ably.pubsub.transport.ITransport; +import io.ably.pubsub.transport.WebSocketTransport; +import io.ably.pubsub.types.AblyException; +import io.ably.pubsub.types.ErrorInfo; +import io.ably.pubsub.types.PresenceMessage; +import io.ably.pubsub.types.ProtocolMessage; /** * Websocket factory that creates transport with capability of modifying the behaviour of send() and other calls diff --git a/lib/src/test/java/io/ably/pubsub/test/util/StatsWriter.java b/lib/src/test/java/io/ably/pubsub/test/util/StatsWriter.java new file mode 100644 index 000000000..5e440ccb0 --- /dev/null +++ b/lib/src/test/java/io/ably/pubsub/test/util/StatsWriter.java @@ -0,0 +1,13 @@ +package io.ably.pubsub.test.util; + +import io.ably.pubsub.http.HttpCore; +import io.ably.pubsub.http.HttpUtils; +import io.ably.pubsub.types.AblyException; +import io.ably.pubsub.types.Stats; +import io.ably.pubsub.util.Serialisation; + +public class StatsWriter { + public static HttpCore.RequestBody asJsonRequest(Stats[] stats) throws AblyException { + return new HttpUtils.JsonRequestBody(Serialisation.gson.toJson(stats)); + } +} diff --git a/lib/src/test/java/io/ably/lib/test/util/StatusHandler.java b/lib/src/test/java/io/ably/pubsub/test/util/StatusHandler.java similarity index 97% rename from lib/src/test/java/io/ably/lib/test/util/StatusHandler.java rename to lib/src/test/java/io/ably/pubsub/test/util/StatusHandler.java index 8e5930d7f..2685cc168 100644 --- a/lib/src/test/java/io/ably/lib/test/util/StatusHandler.java +++ b/lib/src/test/java/io/ably/pubsub/test/util/StatusHandler.java @@ -1,4 +1,4 @@ -package io.ably.lib.test.util; +package io.ably.pubsub.test.util; import fi.iki.elonen.NanoHTTPD; import fi.iki.elonen.router.RouterNanoHTTPD; diff --git a/lib/src/test/java/io/ably/lib/test/util/TestCases.java b/lib/src/test/java/io/ably/pubsub/test/util/TestCases.java similarity index 93% rename from lib/src/test/java/io/ably/lib/test/util/TestCases.java rename to lib/src/test/java/io/ably/pubsub/test/util/TestCases.java index 57aefe952..6d2a05689 100644 --- a/lib/src/test/java/io/ably/lib/test/util/TestCases.java +++ b/lib/src/test/java/io/ably/pubsub/test/util/TestCases.java @@ -1,8 +1,8 @@ -package io.ably.lib.test.util; +package io.ably.pubsub.test.util; -import io.ably.lib.test.common.Helpers; -import io.ably.lib.types.AblyException; -import io.ably.lib.util.Log; +import io.ably.pubsub.test.common.Helpers; +import io.ably.pubsub.types.AblyException; +import io.ably.pubsub.util.Log; import java.util.ArrayList; diff --git a/lib/src/test/java/io/ably/lib/test/util/TimeHandler.java b/lib/src/test/java/io/ably/pubsub/test/util/TimeHandler.java similarity index 96% rename from lib/src/test/java/io/ably/lib/test/util/TimeHandler.java rename to lib/src/test/java/io/ably/pubsub/test/util/TimeHandler.java index c97ac18f2..bb28e8e19 100644 --- a/lib/src/test/java/io/ably/lib/test/util/TimeHandler.java +++ b/lib/src/test/java/io/ably/pubsub/test/util/TimeHandler.java @@ -1,4 +1,4 @@ -package io.ably.lib.test.util; +package io.ably.pubsub.test.util; import fi.iki.elonen.NanoHTTPD; import fi.iki.elonen.router.RouterNanoHTTPD; diff --git a/lib/src/test/java/io/ably/lib/test/util/TokenServer.java b/lib/src/test/java/io/ably/pubsub/test/util/TokenServer.java similarity index 92% rename from lib/src/test/java/io/ably/lib/test/util/TokenServer.java rename to lib/src/test/java/io/ably/pubsub/test/util/TokenServer.java index 0c99d7188..86866acff 100644 --- a/lib/src/test/java/io/ably/lib/test/util/TokenServer.java +++ b/lib/src/test/java/io/ably/pubsub/test/util/TokenServer.java @@ -24,7 +24,7 @@ * . * */ -package io.ably.lib.test.util; +package io.ably.pubsub.test.util; import java.io.IOException; import java.util.HashMap; @@ -32,20 +32,20 @@ import java.util.Map.Entry; import fi.iki.elonen.NanoHTTPD; -import io.ably.lib.rest.AblyRest; -import io.ably.lib.rest.Auth.TokenDetails; -import io.ably.lib.rest.Auth.TokenParams; -import io.ably.lib.rest.Auth.TokenRequest; -import io.ably.lib.types.AblyException; -import io.ably.lib.types.ErrorInfo; -import io.ably.lib.types.ErrorResponse; -import io.ably.lib.util.Serialisation; +import io.ably.pubsub.http.PubSubHttpClient; +import io.ably.pubsub.http.Auth.TokenDetails; +import io.ably.pubsub.http.Auth.TokenParams; +import io.ably.pubsub.http.Auth.TokenRequest; +import io.ably.pubsub.types.AblyException; +import io.ably.pubsub.types.ErrorInfo; +import io.ably.pubsub.types.ErrorResponse; +import io.ably.pubsub.util.Serialisation; import static fi.iki.elonen.NanoHTTPD.newFixedLengthResponse; public class TokenServer extends NanoHTTPD { - public TokenServer(AblyRest ably, int port) { + public TokenServer(PubSubHttpClient ably, int port) { super(port); this.ably = ably; } @@ -163,6 +163,6 @@ private static Response error2Response(ErrorInfo errorInfo) { return newFixedLengthResponse(getStatus(errorInfo.statusCode), MIME_JSON, Serialisation.gson.toJson(err)); } - private final AblyRest ably; + private final PubSubHttpClient ably; private static final String MIME_JSON = "application/json"; } diff --git a/lib/src/test/java/io/ably/lib/transport/ConnectionManagerClosedErrorTest.java b/lib/src/test/java/io/ably/pubsub/transport/ConnectionManagerClosedErrorTest.java similarity index 78% rename from lib/src/test/java/io/ably/lib/transport/ConnectionManagerClosedErrorTest.java rename to lib/src/test/java/io/ably/pubsub/transport/ConnectionManagerClosedErrorTest.java index 429555ceb..e21a8ed95 100644 --- a/lib/src/test/java/io/ably/lib/transport/ConnectionManagerClosedErrorTest.java +++ b/lib/src/test/java/io/ably/pubsub/transport/ConnectionManagerClosedErrorTest.java @@ -1,17 +1,18 @@ -package io.ably.lib.transport; +package io.ably.pubsub.transport; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.notNullValue; import static org.junit.Assert.assertThat; -import io.ably.lib.debug.DebugOptions; -import io.ably.lib.realtime.AblyRealtime; -import io.ably.lib.realtime.CompletionListener; -import io.ably.lib.realtime.ConnectionState; -import io.ably.lib.test.common.Helpers; -import io.ably.lib.test.util.MockWebsocketFactory; -import io.ably.lib.types.AblyException; -import io.ably.lib.types.ErrorInfo; +import io.ably.pubsub.debug.DebugOptions; +import io.ably.pubsub.realtime.CompletionListener; +import io.ably.pubsub.realtime.ConnectionState; +import io.ably.pubsub.realtime.PubSubRealtimeClient; +import io.ably.pubsub.realtime.RealtimeClientFactory; +import io.ably.pubsub.test.common.Helpers; +import io.ably.pubsub.test.util.MockWebsocketFactory; +import io.ably.pubsub.types.AblyException; +import io.ably.pubsub.types.ErrorInfo; import java.util.concurrent.atomic.AtomicReference; import org.junit.Test; @@ -29,7 +30,7 @@ public void closed_connection_error_codes() throws AblyException { mockTransport.failConnect(); options.transportFactory = mockTransport; - try (AblyRealtime ably = new AblyRealtime(options)) { + try (PubSubRealtimeClient ably = RealtimeClientFactory.create(options)) { Helpers.ConnectionWaiter connectionWaiter = new Helpers.ConnectionWaiter(ably.connection); ably.connection.connect(); assertThat(connectionWaiter.waitFor(ConnectionState.disconnected, 1, 10000), is(true)); diff --git a/lib/src/test/java/io/ably/lib/transport/ConnectionManagerPingErrorTest.java b/lib/src/test/java/io/ably/pubsub/transport/ConnectionManagerPingErrorTest.java similarity index 73% rename from lib/src/test/java/io/ably/lib/transport/ConnectionManagerPingErrorTest.java rename to lib/src/test/java/io/ably/pubsub/transport/ConnectionManagerPingErrorTest.java index a3b17429d..209f272cf 100644 --- a/lib/src/test/java/io/ably/lib/transport/ConnectionManagerPingErrorTest.java +++ b/lib/src/test/java/io/ably/pubsub/transport/ConnectionManagerPingErrorTest.java @@ -1,14 +1,15 @@ -package io.ably.lib.transport; +package io.ably.pubsub.transport; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.notNullValue; import static org.junit.Assert.assertThat; -import io.ably.lib.realtime.AblyRealtime; -import io.ably.lib.realtime.CompletionListener; -import io.ably.lib.types.AblyException; -import io.ably.lib.types.ClientOptions; -import io.ably.lib.types.ErrorInfo; +import io.ably.pubsub.realtime.CompletionListener; +import io.ably.pubsub.realtime.PubSubRealtimeClient; +import io.ably.pubsub.realtime.RealtimeClientFactory; +import io.ably.pubsub.types.AblyException; +import io.ably.pubsub.types.ClientOptions; +import io.ably.pubsub.types.ErrorInfo; import java.util.concurrent.atomic.AtomicReference; import org.junit.Test; @@ -22,7 +23,7 @@ public void ping_when_not_connected_error_codes() throws AblyException { ClientOptions options = new ClientOptions("appid.keyid:keysecret"); options.autoConnect = false; AtomicReference error = new AtomicReference<>(); - try (AblyRealtime ably = new AblyRealtime(options)) { + try (PubSubRealtimeClient ably = RealtimeClientFactory.create(options)) { ably.connection.ping(new CompletionListener() { @Override public void onSuccess() {} diff --git a/lib/src/test/java/io/ably/pubsub/transport/DefaultsTest.java b/lib/src/test/java/io/ably/pubsub/transport/DefaultsTest.java new file mode 100644 index 000000000..b18150e2c --- /dev/null +++ b/lib/src/test/java/io/ably/pubsub/transport/DefaultsTest.java @@ -0,0 +1,72 @@ +package io.ably.pubsub.transport; + +import org.junit.Test; + +import static org.hamcrest.Matchers.emptyArray; +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertThat; + +public class DefaultsTest { + + @Test + public void protocol_version_CSV2() { + assertThat(Defaults.ABLY_PROTOCOL_VERSION, is("6")); + } + + /** + * Spec: REC1a, REC2c1 + */ + @Test + public void default_endpoint() { + assertThat(Defaults.getPrimaryDomain(null), is("main.realtime.ably.net")); + assertThat(Defaults.getEndpointFallbackHosts(null), is(new String[] { + "main.a.fallback.ably-realtime.com", + "main.b.fallback.ably-realtime.com", + "main.c.fallback.ably-realtime.com", + "main.d.fallback.ably-realtime.com", + "main.e.fallback.ably-realtime.com" + })); + assertThat(Defaults.HOST_FALLBACKS, is(Defaults.getEndpointFallbackHosts(null))); + } + + /** + * Spec: REC1b4, REC2c4 + */ + @Test + public void routing_policy_endpoint() { + assertThat(Defaults.getPrimaryDomain("acme"), is("acme.realtime.ably.net")); + assertThat(Defaults.getEndpointFallbackHosts("acme"), is(new String[] { + "acme.a.fallback.ably-realtime.com", + "acme.b.fallback.ably-realtime.com", + "acme.c.fallback.ably-realtime.com", + "acme.d.fallback.ably-realtime.com", + "acme.e.fallback.ably-realtime.com" + })); + } + + /** + * Spec: REC1b3, REC2c3 + */ + @Test + public void nonprod_routing_policy_endpoint() { + assertThat(Defaults.getPrimaryDomain("nonprod:sandbox"), is("sandbox.realtime.ably-nonprod.net")); + assertThat(Defaults.getEndpointFallbackHosts("nonprod:sandbox"), is(new String[] { + "sandbox.a.fallback.ably-realtime-nonprod.com", + "sandbox.b.fallback.ably-realtime-nonprod.com", + "sandbox.c.fallback.ably-realtime-nonprod.com", + "sandbox.d.fallback.ably-realtime-nonprod.com", + "sandbox.e.fallback.ably-realtime-nonprod.com" + })); + } + + /** + * Spec: REC1b2, REC2c2 + */ + @Test + public void hostname_endpoint() { + for (String hostname : new String[] { "foo.example.com", "localhost", "127.0.0.1", "::1" }) { + assertThat(Defaults.getPrimaryDomain(hostname), is(hostname)); + assertThat(Defaults.getEndpointFallbackHosts(hostname), is(emptyArray())); + } + } +} diff --git a/lib/src/test/java/io/ably/pubsub/transport/HostsTest.java b/lib/src/test/java/io/ably/pubsub/transport/HostsTest.java new file mode 100644 index 000000000..c47dc1d2b --- /dev/null +++ b/lib/src/test/java/io/ably/pubsub/transport/HostsTest.java @@ -0,0 +1,178 @@ +package io.ably.pubsub.transport; + +import static org.hamcrest.Matchers.contains; +import static org.hamcrest.Matchers.containsInAnyOrder; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.not; +import static org.hamcrest.Matchers.nullValue; +import static org.junit.Assert.assertThat; + +import io.ably.pubsub.types.ClientOptions; +import java.util.ArrayList; +import java.util.List; +import org.junit.Test; + +public class HostsTest { + + private final ClientOptions options = new ClientOptions(); + + /** + * Expect the default primary host and shuffled default fallback hosts when no endpoint is set. + */ + @Test + public void hosts_fallback_no_endpoint() { + // When + Hosts hosts = new Hosts(options); + + // Then + List fallbackHosts = collectFallbackHosts(hosts); + assertThat(hosts.getPrimaryHost(), is("main.realtime.ably.net")); + // the returned fallback hosts should have the same elements as default host fallbacks + assertThat(fallbackHosts, containsInAnyOrder(Defaults.HOST_FALLBACKS)); + // expect the fallback hosts to be shuffled + assertThat(fallbackHosts, not(contains(Defaults.HOST_FALLBACKS))); + } + + /** + * Expect a null, when we provide empty array of fallback hosts + */ + @Test + public void hosts_fallback_empty_array() { + // Given + options.fallbackHosts = new String[] {}; + + // When + Hosts hosts = new Hosts(options); + + // Then + assertThat(hosts.getFallback(hosts.getPrimaryHost()), nullValue()); + } + + /** + * Expect that returned host is contained within custom host list in options, + * but in shuffled order and the right number of them. + */ + @Test + public void hosts_fallback_custom_hosts() { + // Given + String[] customHosts = { "F.ably-realtime.com", "G.ably-realtime.com", "H.ably-realtime.com", "I.ably-realtime.com", "J.ably-realtime.com", "K.ably-realtime.com" }; + options.fallbackHosts = customHosts; + + // When + Hosts hosts = new Hosts(options); + + // Then + List fallbackHosts = collectFallbackHosts(hosts); + assertThat(hosts.getPrimaryHost(), is("main.realtime.ably.net")); + // the returned fallback hosts should have the same elements as custom host fallbacks + assertThat(fallbackHosts, containsInAnyOrder(customHosts)); + // expect the fallback hosts to be shuffled + assertThat(fallbackHosts, not(contains(customHosts))); + } + + /** + * Expect the routing policy's primary host and fallback hosts. + *

+ * Spec: REC1b4, REC2c4 + */ + @Test + public void hosts_routing_policy_endpoint() { + // Given + options.endpoint = "acme"; + + // When + Hosts hosts = new Hosts(options); + + // Then + assertThat(hosts.getPrimaryHost(), is("acme.realtime.ably.net")); + assertThat(collectFallbackHosts(hosts), containsInAnyOrder(Defaults.getEndpointFallbackHosts("acme"))); + } + + /** + * Expect the nonprod routing policy's primary host and fallback hosts. + *

+ * Spec: REC1b3, REC2c3 + */ + @Test + public void hosts_nonprod_endpoint() { + // Given + options.endpoint = "nonprod:sandbox"; + + // When + Hosts hosts = new Hosts(options); + + // Then + assertThat(hosts.getPrimaryHost(), is("sandbox.realtime.ably-nonprod.net")); + assertThat(collectFallbackHosts(hosts), containsInAnyOrder( + "sandbox.a.fallback.ably-realtime-nonprod.com", + "sandbox.b.fallback.ably-realtime-nonprod.com", + "sandbox.c.fallback.ably-realtime-nonprod.com", + "sandbox.d.fallback.ably-realtime-nonprod.com", + "sandbox.e.fallback.ably-realtime-nonprod.com" + )); + } + + /** + * Expect a null fallback when the endpoint is a hostname. + *

+ * Spec: REC1b2, REC2c2 + */ + @Test + public void hosts_no_fallback_for_hostname_endpoint() { + // Given + String host = "overridden.ably.io"; + options.endpoint = host; + + // When + Hosts hosts = new Hosts(options); + + // Then + assertThat(hosts.getPrimaryHost(), is(host)); + assertThat(hosts.getFallback(host), nullValue()); + } + + /** + * Expect custom fallback hosts to be used even when the endpoint is a hostname. + *

+ * Spec: REC2a2 + */ + @Test + public void hosts_fallback_for_hostname_endpoint_and_fallback_hosts() { + // Given + options.endpoint = "custom.ably.com"; + options.fallbackHosts = new String[] { "custom-fallback.ably.com" }; + + // When + Hosts hosts = new Hosts(options); + + // Then + assertThat(hosts.getFallback("custom.ably.com"), is("custom-fallback.ably.com")); + } + + /** + * Expect default fallback hosts even when a custom port is specified. + *

+ * Spec: REC2c1 + */ + @Test + public void hosts_fallback_when_port_is_defined() { + // Given + options.port = 8080; + options.tlsPort = 8081; + + // When + Hosts hosts = new Hosts(options); + + // Then + assertThat(collectFallbackHosts(hosts), containsInAnyOrder(Defaults.HOST_FALLBACKS)); + } + + private List collectFallbackHosts(Hosts hosts) { + List fallbackHosts = new ArrayList<>(); + String host = hosts.getPrimaryHost(); + while ((host = hosts.getFallback(host)) != null){ + fallbackHosts.add(host); + } + return fallbackHosts; + } +} diff --git a/lib/src/test/java/io/ably/lib/transport/SafeSSLSocketFactoryTest.java b/lib/src/test/java/io/ably/pubsub/transport/SafeSSLSocketFactoryTest.java similarity index 98% rename from lib/src/test/java/io/ably/lib/transport/SafeSSLSocketFactoryTest.java rename to lib/src/test/java/io/ably/pubsub/transport/SafeSSLSocketFactoryTest.java index 7feae94cd..af5015ec9 100644 --- a/lib/src/test/java/io/ably/lib/transport/SafeSSLSocketFactoryTest.java +++ b/lib/src/test/java/io/ably/pubsub/transport/SafeSSLSocketFactoryTest.java @@ -1,4 +1,4 @@ -package io.ably.lib.transport; +package io.ably.pubsub.transport; import org.junit.Assert; import org.junit.Before; diff --git a/lib/src/test/java/io/ably/lib/transport/WebSocketTransportTest.java b/lib/src/test/java/io/ably/pubsub/transport/WebSocketTransportTest.java similarity index 93% rename from lib/src/test/java/io/ably/lib/transport/WebSocketTransportTest.java rename to lib/src/test/java/io/ably/pubsub/transport/WebSocketTransportTest.java index c9baad554..042493ab4 100644 --- a/lib/src/test/java/io/ably/lib/transport/WebSocketTransportTest.java +++ b/lib/src/test/java/io/ably/pubsub/transport/WebSocketTransportTest.java @@ -1,13 +1,13 @@ -package io.ably.lib.transport; - -import io.ably.lib.network.WebSocketClient; -import io.ably.lib.network.WebSocketEngine; -import io.ably.lib.network.WebSocketListener; -import io.ably.lib.test.common.Helpers; -import io.ably.lib.test.util.EmptyPlatformAgentProvider; -import io.ably.lib.transport.ITransport.TransportParams; -import io.ably.lib.types.ClientOptions; -import io.ably.lib.types.Param; +package io.ably.pubsub.transport; + +import io.ably.pubsub.network.WebSocketClient; +import io.ably.pubsub.network.WebSocketEngine; +import io.ably.pubsub.network.WebSocketListener; +import io.ably.pubsub.test.common.Helpers; +import io.ably.pubsub.test.util.EmptyPlatformAgentProvider; +import io.ably.pubsub.transport.ITransport.TransportParams; +import io.ably.pubsub.types.ClientOptions; +import io.ably.pubsub.types.Param; import org.junit.Before; import org.junit.Test; diff --git a/lib/src/test/java/io/ably/lib/types/CapabilityTest.java b/lib/src/test/java/io/ably/pubsub/types/CapabilityTest.java similarity index 93% rename from lib/src/test/java/io/ably/lib/types/CapabilityTest.java rename to lib/src/test/java/io/ably/pubsub/types/CapabilityTest.java index 74efbee91..f6ca978cf 100644 --- a/lib/src/test/java/io/ably/lib/types/CapabilityTest.java +++ b/lib/src/test/java/io/ably/pubsub/types/CapabilityTest.java @@ -1,4 +1,4 @@ -package io.ably.lib.types; +package io.ably.pubsub.types; import static org.junit.Assert.assertNull; diff --git a/lib/src/test/java/io/ably/pubsub/types/ClientOptionsTest.java b/lib/src/test/java/io/ably/pubsub/types/ClientOptionsTest.java new file mode 100644 index 000000000..a8d05e62f --- /dev/null +++ b/lib/src/test/java/io/ably/pubsub/types/ClientOptionsTest.java @@ -0,0 +1,40 @@ +package io.ably.pubsub.types; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; + +import java.util.HashMap; + +import org.junit.Test; + +public class ClientOptionsTest { + + private final ClientOptions clientOptions = new ClientOptions(); + + @Test + public void should_support_idempotent_rest_publishing() { + // Then + assertTrue(clientOptions.idempotentRestPublishing); + } + + @Test + public void copy_carries_headers_fallbackHosts_transportParams_and_agents() { + // Given + clientOptions.headers = new HashMap<>(); + clientOptions.headers.put("X-Custom", "value"); + clientOptions.fallbackHosts = new String[]{"a.example.com", "b.example.com"}; + clientOptions.transportParams = new Param[]{new Param("remainPresentFor", "1000")}; + clientOptions.agents = new HashMap<>(); + clientOptions.agents.put("some-sdk", "1.2.3"); + + // When + ClientOptions copied = clientOptions.copy(); + + // Then + assertSame(clientOptions.headers, copied.headers); + assertArrayEquals(clientOptions.fallbackHosts, copied.fallbackHosts); + assertSame(clientOptions.transportParams, copied.transportParams); + assertSame(clientOptions.agents, copied.agents); + } +} diff --git a/lib/src/test/java/io/ably/lib/types/MessageExtrasTest.java b/lib/src/test/java/io/ably/pubsub/types/MessageExtrasTest.java similarity index 96% rename from lib/src/test/java/io/ably/lib/types/MessageExtrasTest.java rename to lib/src/test/java/io/ably/pubsub/types/MessageExtrasTest.java index 5472d9f61..9ea0d51a7 100644 --- a/lib/src/test/java/io/ably/lib/types/MessageExtrasTest.java +++ b/lib/src/test/java/io/ably/pubsub/types/MessageExtrasTest.java @@ -1,8 +1,8 @@ -package io.ably.lib.types; +package io.ably.pubsub.types; import com.google.gson.JsonElement; import com.google.gson.JsonObject; -import io.ably.lib.util.Serialisation; +import io.ably.pubsub.util.Serialisation; import org.junit.Test; import org.msgpack.core.MessagePacker; import org.msgpack.core.MessageUnpacker; diff --git a/lib/src/test/java/io/ably/lib/types/MessageTest.java b/lib/src/test/java/io/ably/pubsub/types/MessageTest.java similarity index 98% rename from lib/src/test/java/io/ably/lib/types/MessageTest.java rename to lib/src/test/java/io/ably/pubsub/types/MessageTest.java index 2bb5dd4a8..8834835df 100644 --- a/lib/src/test/java/io/ably/lib/types/MessageTest.java +++ b/lib/src/test/java/io/ably/pubsub/types/MessageTest.java @@ -1,12 +1,12 @@ -package io.ably.lib.types; +package io.ably.pubsub.types; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; import com.google.gson.JsonElement; import com.google.gson.JsonObject; -import io.ably.lib.types.Message.Serializer; -import io.ably.lib.util.Serialisation; +import io.ably.pubsub.types.Message.Serializer; +import io.ably.pubsub.util.Serialisation; import org.junit.Test; import org.msgpack.core.MessagePacker; import org.msgpack.core.MessageUnpacker; diff --git a/lib/src/test/java/io/ably/lib/types/RecoveryKeyContextTest.java b/lib/src/test/java/io/ably/pubsub/types/RecoveryKeyContextTest.java similarity index 98% rename from lib/src/test/java/io/ably/lib/types/RecoveryKeyContextTest.java rename to lib/src/test/java/io/ably/pubsub/types/RecoveryKeyContextTest.java index 85d9e0127..69f8d8856 100644 --- a/lib/src/test/java/io/ably/lib/types/RecoveryKeyContextTest.java +++ b/lib/src/test/java/io/ably/pubsub/types/RecoveryKeyContextTest.java @@ -1,4 +1,4 @@ -package io.ably.lib.types; +package io.ably.pubsub.types; import org.junit.Test; diff --git a/lib/src/test/java/io/ably/lib/types/SummaryTest.java b/lib/src/test/java/io/ably/pubsub/types/SummaryTest.java similarity index 99% rename from lib/src/test/java/io/ably/lib/types/SummaryTest.java rename to lib/src/test/java/io/ably/pubsub/types/SummaryTest.java index 12cb37f7a..622c9c835 100644 --- a/lib/src/test/java/io/ably/lib/types/SummaryTest.java +++ b/lib/src/test/java/io/ably/pubsub/types/SummaryTest.java @@ -1,4 +1,4 @@ -package io.ably.lib.types; +package io.ably.pubsub.types; import com.google.gson.JsonArray; import com.google.gson.JsonObject; diff --git a/lib/src/test/java/io/ably/lib/util/AgentHeaderCreatorTest.java b/lib/src/test/java/io/ably/pubsub/util/AgentHeaderCreatorTest.java similarity index 96% rename from lib/src/test/java/io/ably/lib/util/AgentHeaderCreatorTest.java rename to lib/src/test/java/io/ably/pubsub/util/AgentHeaderCreatorTest.java index 71c926f33..853ffe8d9 100644 --- a/lib/src/test/java/io/ably/lib/util/AgentHeaderCreatorTest.java +++ b/lib/src/test/java/io/ably/pubsub/util/AgentHeaderCreatorTest.java @@ -1,7 +1,7 @@ -package io.ably.lib.util; +package io.ably.pubsub.util; -import io.ably.lib.test.util.EmptyPlatformAgentProvider; -import io.ably.lib.transport.Defaults; +import io.ably.pubsub.test.util.EmptyPlatformAgentProvider; +import io.ably.pubsub.transport.Defaults; import org.junit.Test; import java.util.Arrays; diff --git a/lib/src/test/java/io/ably/lib/util/CryptoMessageTest.java b/lib/src/test/java/io/ably/pubsub/util/CryptoMessageTest.java similarity index 94% rename from lib/src/test/java/io/ably/lib/util/CryptoMessageTest.java rename to lib/src/test/java/io/ably/pubsub/util/CryptoMessageTest.java index 702188cf9..e2a7dd2ae 100644 --- a/lib/src/test/java/io/ably/lib/util/CryptoMessageTest.java +++ b/lib/src/test/java/io/ably/pubsub/util/CryptoMessageTest.java @@ -1,6 +1,6 @@ -package io.ably.lib.util; +package io.ably.pubsub.util; -import static io.ably.lib.test.common.Helpers.assertMessagesEqual; +import static io.ably.pubsub.test.common.Helpers.assertMessagesEqual; import static org.hamcrest.core.StringEndsWith.endsWith; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; @@ -9,17 +9,17 @@ import java.io.IOException; import java.security.NoSuchAlgorithmException; -import io.ably.lib.test.util.AblyCommonsReader; +import io.ably.pubsub.test.util.AblyCommonsReader; import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import org.junit.runners.Parameterized.Parameters; -import io.ably.lib.types.AblyException; -import io.ably.lib.types.ChannelOptions; -import io.ably.lib.types.Message; -import io.ably.lib.util.Crypto.CipherParams; +import io.ably.pubsub.types.AblyException; +import io.ably.pubsub.types.ChannelOptions; +import io.ably.pubsub.types.Message; +import io.ably.pubsub.util.Crypto.CipherParams; @Ignore("FIXME: Initialization is failing") @RunWith(Parameterized.class) diff --git a/lib/src/test/java/io/ably/lib/util/CryptoTest.java b/lib/src/test/java/io/ably/pubsub/util/CryptoTest.java similarity index 97% rename from lib/src/test/java/io/ably/lib/util/CryptoTest.java rename to lib/src/test/java/io/ably/pubsub/util/CryptoTest.java index d1af39cb7..a03b6b59d 100644 --- a/lib/src/test/java/io/ably/lib/util/CryptoTest.java +++ b/lib/src/test/java/io/ably/pubsub/util/CryptoTest.java @@ -1,4 +1,4 @@ -package io.ably.lib.util; +package io.ably.pubsub.util; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; @@ -17,10 +17,10 @@ import com.google.gson.stream.JsonWriter; -import io.ably.lib.types.AblyException; -import io.ably.lib.util.Crypto.CipherParams; -import io.ably.lib.util.Crypto.EncryptingChannelCipher; -import io.ably.lib.util.CryptoMessageTest.FixtureSet; +import io.ably.pubsub.types.AblyException; +import io.ably.pubsub.util.Crypto.CipherParams; +import io.ably.pubsub.util.Crypto.EncryptingChannelCipher; +import io.ably.pubsub.util.CryptoMessageTest.FixtureSet; public class CryptoTest { /** diff --git a/lib/src/test/java/io/ably/lib/util/EventEmitterTest.java b/lib/src/test/java/io/ably/pubsub/util/EventEmitterTest.java similarity index 99% rename from lib/src/test/java/io/ably/lib/util/EventEmitterTest.java rename to lib/src/test/java/io/ably/pubsub/util/EventEmitterTest.java index d56a0e0c9..a6e37dded 100644 --- a/lib/src/test/java/io/ably/lib/util/EventEmitterTest.java +++ b/lib/src/test/java/io/ably/pubsub/util/EventEmitterTest.java @@ -1,4 +1,4 @@ -package io.ably.lib.util; +package io.ably.pubsub.util; import org.junit.Test; diff --git a/lib/src/test/java/io/ably/lib/util/ParamsUtilsTest.java b/lib/src/test/java/io/ably/pubsub/util/ParamsUtilsTest.java similarity index 92% rename from lib/src/test/java/io/ably/lib/util/ParamsUtilsTest.java rename to lib/src/test/java/io/ably/pubsub/util/ParamsUtilsTest.java index 04df947c2..6c5d2859e 100644 --- a/lib/src/test/java/io/ably/lib/util/ParamsUtilsTest.java +++ b/lib/src/test/java/io/ably/pubsub/util/ParamsUtilsTest.java @@ -1,8 +1,8 @@ -package io.ably.lib.util; +package io.ably.pubsub.util; -import io.ably.lib.types.AblyException; -import io.ably.lib.types.ClientOptions; -import io.ably.lib.types.Param; +import io.ably.pubsub.types.AblyException; +import io.ably.pubsub.types.ClientOptions; +import io.ably.pubsub.types.Param; import org.junit.Test; import static org.junit.Assert.assertEquals; diff --git a/lib/src/test/java/io/ably/lib/util/ReconnectionStrategyTest.java b/lib/src/test/java/io/ably/pubsub/util/ReconnectionStrategyTest.java similarity index 94% rename from lib/src/test/java/io/ably/lib/util/ReconnectionStrategyTest.java rename to lib/src/test/java/io/ably/pubsub/util/ReconnectionStrategyTest.java index 4569d1790..a8fb81dba 100644 --- a/lib/src/test/java/io/ably/lib/util/ReconnectionStrategyTest.java +++ b/lib/src/test/java/io/ably/pubsub/util/ReconnectionStrategyTest.java @@ -1,10 +1,10 @@ -package io.ably.lib.util; +package io.ably.pubsub.util; import org.junit.Test; import java.util.Arrays; -import static io.ably.lib.test.common.Helpers.assertTimeoutBetween; +import static io.ably.pubsub.test.common.Helpers.assertTimeoutBetween; public class ReconnectionStrategyTest { diff --git a/lib/src/test/kotlin/io/ably/lib/uts/deviations.md b/lib/src/test/kotlin/io/ably/pubsub/uts/deviations.md similarity index 96% rename from lib/src/test/kotlin/io/ably/lib/uts/deviations.md rename to lib/src/test/kotlin/io/ably/pubsub/uts/deviations.md index 892d97ea4..f0f285538 100644 --- a/lib/src/test/kotlin/io/ably/lib/uts/deviations.md +++ b/lib/src/test/kotlin/io/ably/pubsub/uts/deviations.md @@ -1,11 +1,11 @@ -# Deviations — UTS realtime/rest suites (`io.ably.lib.uts.*`) +# Deviations — UTS realtime/rest suites (`io.ably.pubsub.uts.*`) > **Scope:** this file lives alongside the realtime/rest UTS suites in the `:java` module -> (`lib/src/test/kotlin/io/ably/lib/uts/`) and holds deviations for the **realtime/rest tiers** it +> (`lib/src/test/kotlin/io/ably/pubsub/uts/`) and holds deviations for the **realtime/rest tiers** it > hosts. All **objects** tiers (unit, integration and proxy) moved to `:liveobjects`'s own test source > set alongside the tests they document; their deviations (the typed-SDK / language adaptations, the > intentional RTO18d entry, and any objects integration/proxy entries) are in -> `liveobjects/src/test/kotlin/io/ably/lib/liveobjects/uts/deviations.md`. For the shared UTS infra these +> `liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/uts/deviations.md`. For the shared UTS infra these > suites consume, the tier smoke examples, and the `RUN_DEVIATIONS` mechanism, see `uts/README.md`. > > Records every place a generated test deviates from its UTS spec, using the manual's **Recording diff --git a/lib/src/test/kotlin/io/ably/lib/uts/integration/proxy/realtime/AuthReauthTest.kt b/lib/src/test/kotlin/io/ably/pubsub/uts/integration/proxy/realtime/AuthReauthTest.kt similarity index 77% rename from lib/src/test/kotlin/io/ably/lib/uts/integration/proxy/realtime/AuthReauthTest.kt rename to lib/src/test/kotlin/io/ably/pubsub/uts/integration/proxy/realtime/AuthReauthTest.kt index 9ae78cbd5..e4b37161c 100644 --- a/lib/src/test/kotlin/io/ably/lib/uts/integration/proxy/realtime/AuthReauthTest.kt +++ b/lib/src/test/kotlin/io/ably/pubsub/uts/integration/proxy/realtime/AuthReauthTest.kt @@ -1,15 +1,16 @@ -package io.ably.lib.uts.integration.proxy.realtime - -import io.ably.lib.realtime.ConnectionState -import io.ably.lib.rest.AblyRest -import io.ably.lib.rest.Auth -import io.ably.lib.uts.infra.awaitState -import io.ably.lib.uts.infra.integration.SandboxApp -import io.ably.lib.uts.infra.integration.proxy.ProxyManager -import io.ably.lib.uts.infra.integration.proxy.ProxySession -import io.ably.lib.uts.infra.integration.proxy.connectThroughProxy -import io.ably.lib.uts.infra.pollUntil -import io.ably.lib.uts.infra.unit.TestRealtimeClient +package io.ably.pubsub.uts.integration.proxy.realtime + +import io.ably.pubsub.realtime.ConnectionState +import io.ably.pubsub.http.Auth +import io.ably.pubsub.uts.infra.awaitState +import io.ably.pubsub.uts.infra.integration.AblyJwt +import io.ably.pubsub.uts.infra.integration.SandboxApp +import io.ably.pubsub.uts.infra.integration.proxy.ProxyManager +import io.ably.pubsub.uts.infra.integration.proxy.ProxySession +import io.ably.pubsub.uts.infra.integration.proxy.connectThroughProxy +import io.ably.pubsub.uts.infra.pollUntil +import io.ably.pubsub.uts.infra.unit.TestRealtimeClient +import io.ably.pubsub.uts.infra.unit.utsSide import kotlinx.coroutines.runBlocking import kotlinx.coroutines.test.runTest import org.junit.jupiter.api.AfterAll @@ -59,14 +60,19 @@ class AuthReauthTest { val session = ProxySession.create(rules = emptyList()) // Re-authentication is observed via an authCallback. The spec generates a JWT from the - // sandbox key parts; the idiomatic ably-java equivalent is a locally-signed TokenRequest - // produced from the same key — no external JWT library required. The realtime client then - // exchanges it for a token (through the proxy), satisfying RTC8a. - val tokenSigner = AblyRest(app.defaultKey) + // sandbox key parts, and so does this test (AblyJwt: HS256 via JDK crypto, no external + // library). A JWT rather than a native TokenRequest is load-bearing on the server UTS + // leg: a token-authenticated client may declare the server side only via the signed + // x-ably-clientType claim, which the native token format cannot carry yet — so the JWT + // carries the claim on the server leg, and this test runs on every leg. val authCallbackCount = AtomicInteger(0) val authCallback = Auth.TokenCallback { params -> authCallbackCount.incrementAndGet() - tokenSigner.auth.createTokenRequest(params, null) + AblyJwt.sign( + app.defaultKey, + clientId = params.clientId, + clientType = if (utsSide == "server") "server" else null, + ) } // Keep the JSON protocol (ClientOptionsBuilder default): the proxy injects/inspects frames @@ -128,13 +134,12 @@ class AuthReauthTest { "Expected at least one client-to-server AUTH frame carrying auth details", ) } finally { - // Nest teardown so session/tokenSigner are always cleaned up even if close-wait times out. + // Nest teardown so the session is always cleaned up even if close-wait times out. try { client.close() awaitState(client, ConnectionState.closed, 10.seconds) } finally { session.close() - runCatching { tokenSigner.close() } } } } diff --git a/lib/src/test/kotlin/io/ably/lib/uts/integration/standard/realtime/ChannelHistoryTest.kt b/lib/src/test/kotlin/io/ably/pubsub/uts/integration/standard/realtime/ChannelHistoryTest.kt similarity index 84% rename from lib/src/test/kotlin/io/ably/lib/uts/integration/standard/realtime/ChannelHistoryTest.kt rename to lib/src/test/kotlin/io/ably/pubsub/uts/integration/standard/realtime/ChannelHistoryTest.kt index 56b8f39d7..7e636d546 100644 --- a/lib/src/test/kotlin/io/ably/lib/uts/integration/standard/realtime/ChannelHistoryTest.kt +++ b/lib/src/test/kotlin/io/ably/pubsub/uts/integration/standard/realtime/ChannelHistoryTest.kt @@ -1,20 +1,20 @@ -package io.ably.lib.uts.integration.standard.realtime - -import io.ably.lib.realtime.AblyRealtime -import io.ably.lib.realtime.Channel -import io.ably.lib.realtime.ChannelState -import io.ably.lib.realtime.ConnectionState -import io.ably.lib.types.AblyException -import io.ably.lib.types.Callback -import io.ably.lib.types.ErrorInfo -import io.ably.lib.types.Message -import io.ably.lib.types.PaginatedResult -import io.ably.lib.types.PublishResult -import io.ably.lib.uts.infra.awaitChannelState -import io.ably.lib.uts.infra.awaitState -import io.ably.lib.uts.infra.integration.SandboxApp -import io.ably.lib.uts.infra.pollUntil -import io.ably.lib.uts.infra.unit.TestRealtimeClient +package io.ably.pubsub.uts.integration.standard.realtime + +import io.ably.pubsub.realtime.PubSubRealtimeClient +import io.ably.pubsub.realtime.Channel +import io.ably.pubsub.realtime.ChannelState +import io.ably.pubsub.realtime.ConnectionState +import io.ably.pubsub.types.AblyException +import io.ably.pubsub.types.Callback +import io.ably.pubsub.types.ErrorInfo +import io.ably.pubsub.types.Message +import io.ably.pubsub.types.PaginatedResult +import io.ably.pubsub.types.PublishResult +import io.ably.pubsub.uts.infra.awaitChannelState +import io.ably.pubsub.uts.infra.awaitState +import io.ably.pubsub.uts.infra.integration.SandboxApp +import io.ably.pubsub.uts.infra.pollUntil +import io.ably.pubsub.uts.infra.unit.TestRealtimeClient import kotlinx.coroutines.runBlocking import kotlinx.coroutines.suspendCancellableCoroutine import kotlinx.coroutines.test.runTest @@ -116,10 +116,9 @@ class ChannelHistoryTest { // ── helpers ────────────────────────────────────────────────────────────── /** A realtime client wired straight to the nonprod sandbox (no proxy). */ - private fun newClient(useBinaryProtocol: Boolean): AblyRealtime = TestRealtimeClient { + private fun newClient(useBinaryProtocol: Boolean): PubSubRealtimeClient = TestRealtimeClient { key = app.defaultKey - realtimeHost = SandboxApp.sandboxHost - restHost = SandboxApp.sandboxHost + endpoint = SandboxApp.sandboxEndpoint this.useBinaryProtocol = useBinaryProtocol autoConnect = false } diff --git a/lib/src/test/kotlin/io/ably/lib/uts/integration/standard/realtime/TokenRequestTest.kt b/lib/src/test/kotlin/io/ably/pubsub/uts/integration/standard/realtime/TokenRequestTest.kt similarity index 67% rename from lib/src/test/kotlin/io/ably/lib/uts/integration/standard/realtime/TokenRequestTest.kt rename to lib/src/test/kotlin/io/ably/pubsub/uts/integration/standard/realtime/TokenRequestTest.kt index f91d8da07..50b7a1c83 100644 --- a/lib/src/test/kotlin/io/ably/lib/uts/integration/standard/realtime/TokenRequestTest.kt +++ b/lib/src/test/kotlin/io/ably/pubsub/uts/integration/standard/realtime/TokenRequestTest.kt @@ -1,11 +1,13 @@ -package io.ably.lib.uts.integration.standard.realtime +package io.ably.pubsub.uts.integration.standard.realtime -import io.ably.lib.realtime.ConnectionState -import io.ably.lib.rest.Auth -import io.ably.lib.uts.infra.awaitState -import io.ably.lib.uts.infra.integration.SandboxApp -import io.ably.lib.uts.infra.unit.TestRealtimeClient -import io.ably.lib.uts.infra.unit.TestRestClient +import io.ably.pubsub.realtime.PubSubRealtimeClient +import io.ably.pubsub.realtime.RealtimeClientFactory +import io.ably.pubsub.realtime.ConnectionState +import io.ably.pubsub.http.Auth +import io.ably.pubsub.uts.infra.awaitState +import io.ably.pubsub.uts.infra.integration.SandboxApp +import io.ably.pubsub.uts.infra.unit.ClientOptionsBuilder +import io.ably.pubsub.uts.infra.unit.TestHttpClient import kotlinx.coroutines.runBlocking import kotlinx.coroutines.test.runTest import org.junit.jupiter.api.AfterAll @@ -29,6 +31,14 @@ import kotlin.time.Duration.Companion.seconds * server. A REST client signs the TokenRequest; a separate realtime client exchanges it (through * its `authCallback`) for a token and connects, proving the server accepted it. * + * The two clients deliberately sit on different sides of the seam. The **minting** client — the + * RSA9 surface under test — goes through [TestHttpClient], so on the server UTS leg it exercises + * `createTokenRequest` through the server door, the shape a real server has: mint native tokens + * for others. The **consuming** client models the device those tokens are minted for, so it is + * always a plain core client: a client may not authenticate *itself* with a native token while + * declaring the server side (realtime rejects that with 40167 — on token auth the side must come + * from the signed x-ably-clientType claim, which the native token format cannot carry). + * * Spec points: RSA9, RSA9a, RSA9g. Source spec: `realtime/integration/auth/token_request_test.md`. */ @TestInstance(TestInstance.Lifecycle.PER_CLASS) @@ -46,6 +56,10 @@ class TokenRequestTest { if (::app.isInitialized) app.delete() } + /** The token-consuming client — a plain core client on every leg; see the class doc. */ + private fun tokenConsumingClient(block: ClientOptionsBuilder.() -> Unit): PubSubRealtimeClient = + RealtimeClientFactory.create(ClientOptionsBuilder().apply(block)) + /** * @UTS realtime/integration/RSA9a/token-request-server-accepted-0 * @UTS realtime/integration/RSA9g/token-request-server-accepted-0 @@ -53,16 +67,15 @@ class TokenRequestTest { @Test fun `RSA9a, RSA9g - createTokenRequest produces server-accepted token`() = runTest { // Client A signs TokenRequests locally with the API key (no network). - val creator = TestRestClient { + val creator = TestHttpClient { key = app.defaultKey - restHost = SandboxApp.sandboxHost + endpoint = SandboxApp.sandboxEndpoint } // Client B connects using a TokenRequest produced by client A. - val client = TestRealtimeClient { + val client = tokenConsumingClient { authCallback = Auth.TokenCallback { params -> creator.auth.createTokenRequest(params, null) } - realtimeHost = SandboxApp.sandboxHost - restHost = SandboxApp.sandboxHost + endpoint = SandboxApp.sandboxEndpoint useBinaryProtocol = false autoConnect = false } @@ -87,21 +100,20 @@ class TokenRequestTest { fun `RSA9 - createTokenRequest with clientId`() = runTest { val testClientId = "token-request-client-" + UUID.randomUUID() - val creator = TestRestClient { + val creator = TestHttpClient { key = app.defaultKey - restHost = SandboxApp.sandboxHost + endpoint = SandboxApp.sandboxEndpoint } // The TokenRequest is signed with the specific clientId, producing a token that // authenticates the client with that identity. - val client = TestRealtimeClient { + val client = tokenConsumingClient { authCallback = Auth.TokenCallback { params -> params.clientId = testClientId creator.auth.createTokenRequest(params, null) } clientId = testClientId - realtimeHost = SandboxApp.sandboxHost - restHost = SandboxApp.sandboxHost + endpoint = SandboxApp.sandboxEndpoint useBinaryProtocol = false autoConnect = false } diff --git a/lib/src/test/kotlin/io/ably/lib/uts/unit/realtime/ConnectionRecoveryTest.kt b/lib/src/test/kotlin/io/ably/pubsub/uts/unit/realtime/ConnectionRecoveryTest.kt similarity index 96% rename from lib/src/test/kotlin/io/ably/lib/uts/unit/realtime/ConnectionRecoveryTest.kt rename to lib/src/test/kotlin/io/ably/pubsub/uts/unit/realtime/ConnectionRecoveryTest.kt index ade045577..4d9bd652f 100644 --- a/lib/src/test/kotlin/io/ably/lib/uts/unit/realtime/ConnectionRecoveryTest.kt +++ b/lib/src/test/kotlin/io/ably/pubsub/uts/unit/realtime/ConnectionRecoveryTest.kt @@ -1,15 +1,15 @@ -package io.ably.lib.uts.unit.realtime - -import io.ably.lib.uts.infra.unit.* -import io.ably.lib.realtime.ChannelState -import io.ably.lib.realtime.ConnectionState -import io.ably.lib.realtime.ConnectionStateListener -import io.ably.lib.types.ErrorInfo -import io.ably.lib.types.ProtocolMessage -import io.ably.lib.types.RecoveryKeyContext -import io.ably.lib.uts.infra.awaitChannelState -import io.ably.lib.uts.infra.awaitState -import io.ably.lib.uts.infra.pollUntil +package io.ably.pubsub.uts.unit.realtime + +import io.ably.pubsub.uts.infra.unit.* +import io.ably.pubsub.realtime.ChannelState +import io.ably.pubsub.realtime.ConnectionState +import io.ably.pubsub.realtime.ConnectionStateListener +import io.ably.pubsub.types.ErrorInfo +import io.ably.pubsub.types.ProtocolMessage +import io.ably.pubsub.types.RecoveryKeyContext +import io.ably.pubsub.uts.infra.awaitChannelState +import io.ably.pubsub.uts.infra.awaitState +import io.ably.pubsub.uts.infra.pollUntil import kotlinx.coroutines.launch import kotlinx.coroutines.test.runTest import java.util.concurrent.CopyOnWriteArrayList diff --git a/liveobjects/build.gradle.kts b/liveobjects/build.gradle.kts index 58c19a9a7..47482fe1b 100644 --- a/liveobjects/build.gradle.kts +++ b/liveobjects/build.gradle.kts @@ -11,11 +11,11 @@ repositories { } dependencies { - compileOnly(project(":java")) + compileOnly(project(":core")) implementation(libs.bundles.common) implementation(libs.coroutine.core) - testImplementation(project(":java")) + testImplementation(project(":core")) testImplementation(libs.bundles.kotlin.tests) // keeps the JUnit4 API for the ~9 org.junit.* files // Shared UTS test infra + the exported (`api`) test toolkit: JUnit 5 (api+params+engine via the // aggregator), the kotlin.test Jupiter binding and coroutines all arrive transitively from :uts, @@ -42,18 +42,18 @@ tasks.withType().configureEach { tasks.register("runLiveObjectsUnitTests") { filter { - includeTestsMatching("io.ably.lib.liveobjects.unit.*") // the module's own unit tests - includeTestsMatching("io.ably.lib.liveobjects.uts.unit.*") // UTS objects unit suite (skill-generated) + includeTestsMatching("io.ably.pubsub.liveobjects.unit.*") // the module's own unit tests + includeTestsMatching("io.ably.pubsub.liveobjects.uts.unit.*") // UTS objects unit suite (skill-generated) } } tasks.register("runLiveObjectsIntegrationTests") { filter { - includeTestsMatching("io.ably.lib.liveobjects.integration.*") - includeTestsMatching("io.ably.lib.liveobjects.uts.integration.*") // NEW - includeTestsMatching("io.ably.lib.liveobjects.uts.proxy.*") // NEW + includeTestsMatching("io.ably.pubsub.liveobjects.integration.*") + includeTestsMatching("io.ably.pubsub.liveobjects.uts.integration.*") // NEW + includeTestsMatching("io.ably.pubsub.liveobjects.uts.proxy.*") // NEW // Exclude the base integration test class - excludeTestsMatching("io.ably.lib.liveobjects.integration.setup.IntegrationTest") + excludeTestsMatching("io.ably.pubsub.liveobjects.integration.setup.IntegrationTest") } } diff --git a/liveobjects/src/main/kotlin/io/ably/lib/liveobjects/DefaultLiveObjectsPlugin.kt b/liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/DefaultLiveObjectsPlugin.kt similarity index 85% rename from liveobjects/src/main/kotlin/io/ably/lib/liveobjects/DefaultLiveObjectsPlugin.kt rename to liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/DefaultLiveObjectsPlugin.kt index b160f82ee..aa061157c 100644 --- a/liveobjects/src/main/kotlin/io/ably/lib/liveobjects/DefaultLiveObjectsPlugin.kt +++ b/liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/DefaultLiveObjectsPlugin.kt @@ -1,8 +1,8 @@ -package io.ably.lib.liveobjects +package io.ably.pubsub.liveobjects -import io.ably.lib.liveobjects.adapter.AblyClientAdapter -import io.ably.lib.realtime.ChannelState -import io.ably.lib.types.ProtocolMessage +import io.ably.pubsub.liveobjects.adapter.AblyClientAdapter +import io.ably.pubsub.realtime.ChannelState +import io.ably.pubsub.types.ProtocolMessage import java.util.concurrent.ConcurrentHashMap public class DefaultLiveObjectsPlugin(private val adapter: AblyClientAdapter) : LiveObjectsPlugin { diff --git a/liveobjects/src/main/kotlin/io/ably/lib/liveobjects/DefaultRealtimeObject.kt b/liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/DefaultRealtimeObject.kt similarity index 95% rename from liveobjects/src/main/kotlin/io/ably/lib/liveobjects/DefaultRealtimeObject.kt rename to liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/DefaultRealtimeObject.kt index 5827334b7..0aa58d5c6 100644 --- a/liveobjects/src/main/kotlin/io/ably/lib/liveobjects/DefaultRealtimeObject.kt +++ b/liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/DefaultRealtimeObject.kt @@ -1,20 +1,20 @@ -package io.ably.lib.liveobjects - -import io.ably.lib.liveobjects.adapter.AblyClientAdapter -import io.ably.lib.liveobjects.message.WireObjectMessage -import io.ably.lib.liveobjects.path.PathObjectSubscriptionRegister -import io.ably.lib.liveobjects.path.types.DefaultLiveMapPathObject -import io.ably.lib.liveobjects.path.types.LiveMapPathObject -import io.ably.lib.liveobjects.state.ObjectStateChange -import io.ably.lib.liveobjects.state.ObjectStateEvent -import io.ably.lib.liveobjects.value.ObjectType -import io.ably.lib.realtime.ChannelState -import io.ably.lib.types.AblyException -import io.ably.lib.types.ProtocolMessage -import io.ably.lib.types.PublishResult -import io.ably.lib.util.Clock -import io.ably.lib.util.Log -import io.ably.lib.util.SystemClock +package io.ably.pubsub.liveobjects + +import io.ably.pubsub.liveobjects.adapter.AblyClientAdapter +import io.ably.pubsub.liveobjects.message.WireObjectMessage +import io.ably.pubsub.liveobjects.path.PathObjectSubscriptionRegister +import io.ably.pubsub.liveobjects.path.types.DefaultLiveMapPathObject +import io.ably.pubsub.liveobjects.path.types.LiveMapPathObject +import io.ably.pubsub.liveobjects.state.ObjectStateChange +import io.ably.pubsub.liveobjects.state.ObjectStateEvent +import io.ably.pubsub.liveobjects.value.ObjectType +import io.ably.pubsub.realtime.ChannelState +import io.ably.pubsub.types.AblyException +import io.ably.pubsub.types.ProtocolMessage +import io.ably.pubsub.types.PublishResult +import io.ably.pubsub.util.Clock +import io.ably.pubsub.util.Log +import io.ably.pubsub.util.SystemClock import kotlinx.coroutines.* import kotlinx.coroutines.channels.Channel.Factory.UNLIMITED import kotlinx.coroutines.future.future diff --git a/liveobjects/src/main/kotlin/io/ably/lib/liveobjects/Errors.kt b/liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/Errors.kt similarity index 92% rename from liveobjects/src/main/kotlin/io/ably/lib/liveobjects/Errors.kt rename to liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/Errors.kt index e1931d72a..5dcbde76d 100644 --- a/liveobjects/src/main/kotlin/io/ably/lib/liveobjects/Errors.kt +++ b/liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/Errors.kt @@ -1,12 +1,12 @@ -package io.ably.lib.liveobjects +package io.ably.pubsub.liveobjects -import io.ably.lib.types.AblyException -import io.ably.lib.types.ErrorInfo +import io.ably.pubsub.types.AblyException +import io.ably.pubsub.types.ErrorInfo /** * Error codes and helpers for the path-based public API implementation. * Copied (and extended with the path-API codes) from the legacy package so - * this package has no dependency on `io.ably.lib.objects`. + * this package has no dependency on `io.ably.pubsub.objects`. */ internal enum class ObjectErrorCode(val code: Int) { BadRequest(40_000), diff --git a/liveobjects/src/main/kotlin/io/ably/lib/liveobjects/Helpers.kt b/liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/Helpers.kt similarity index 93% rename from liveobjects/src/main/kotlin/io/ably/lib/liveobjects/Helpers.kt rename to liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/Helpers.kt index 3d3437825..2d7534f14 100644 --- a/liveobjects/src/main/kotlin/io/ably/lib/liveobjects/Helpers.kt +++ b/liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/Helpers.kt @@ -1,13 +1,13 @@ -package io.ably.lib.liveobjects - -import io.ably.lib.liveobjects.adapter.AblyClientAdapter -import io.ably.lib.liveobjects.message.WireObjectMessage -import io.ably.lib.liveobjects.message.size -import io.ably.lib.realtime.ChannelState -import io.ably.lib.realtime.CompletionListener -import io.ably.lib.realtime.ConnectionEvent -import io.ably.lib.realtime.ConnectionStateListener -import io.ably.lib.types.* +package io.ably.pubsub.liveobjects + +import io.ably.pubsub.liveobjects.adapter.AblyClientAdapter +import io.ably.pubsub.liveobjects.message.WireObjectMessage +import io.ably.pubsub.liveobjects.message.size +import io.ably.pubsub.realtime.ChannelState +import io.ably.pubsub.realtime.CompletionListener +import io.ably.pubsub.realtime.ConnectionEvent +import io.ably.pubsub.realtime.ConnectionStateListener +import io.ably.pubsub.types.* import kotlinx.coroutines.suspendCancellableCoroutine import java.util.concurrent.atomic.AtomicBoolean import kotlin.coroutines.resume @@ -33,7 +33,7 @@ internal fun onceSubscription(onUnsubscribe: () -> Unit): Subscription { /** * Validates that the channel is configured for the access (read/subscribe) API: it must be * attachable (not detached/failed) and have the `object_subscribe` mode. Copied from the - * legacy `io.ably.lib.objects` helpers so this package has no dependency on that package. + * legacy `io.ably.pubsub.objects` helpers so this package has no dependency on that package. * * Spec: RTO25 */ diff --git a/liveobjects/src/main/kotlin/io/ably/lib/liveobjects/ObjectId.kt b/liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/ObjectId.kt similarity index 96% rename from liveobjects/src/main/kotlin/io/ably/lib/liveobjects/ObjectId.kt rename to liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/ObjectId.kt index 66ff9798a..28c9e8af2 100644 --- a/liveobjects/src/main/kotlin/io/ably/lib/liveobjects/ObjectId.kt +++ b/liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/ObjectId.kt @@ -1,6 +1,6 @@ -package io.ably.lib.liveobjects +package io.ably.pubsub.liveobjects -import io.ably.lib.liveobjects.value.ObjectType +import io.ably.pubsub.liveobjects.value.ObjectType import java.nio.charset.StandardCharsets import java.security.MessageDigest import java.util.Base64 diff --git a/liveobjects/src/main/kotlin/io/ably/lib/liveobjects/ObjectsManager.kt b/liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/ObjectsManager.kt similarity index 95% rename from liveobjects/src/main/kotlin/io/ably/lib/liveobjects/ObjectsManager.kt rename to liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/ObjectsManager.kt index 157b37c12..c9e38cd1a 100644 --- a/liveobjects/src/main/kotlin/io/ably/lib/liveobjects/ObjectsManager.kt +++ b/liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/ObjectsManager.kt @@ -1,17 +1,17 @@ -package io.ably.lib.liveobjects - -import io.ably.lib.liveobjects.message.WireObjectMessage -import io.ably.lib.liveobjects.message.WireObjectOperation -import io.ably.lib.liveobjects.message.WireObjectOperationAction -import io.ably.lib.liveobjects.message.WireObjectState -import io.ably.lib.liveobjects.message.WireObjectsMap -import io.ably.lib.liveobjects.value.BaseRealtimeObject -import io.ably.lib.liveobjects.value.ObjectUpdate -import io.ably.lib.liveobjects.value.noOp -import io.ably.lib.liveobjects.value.livecounter.InternalLiveCounter -import io.ably.lib.liveobjects.value.livemap.InternalLiveMap -import io.ably.lib.liveobjects.value.livemap.isEntryOrRefTombstoned -import io.ably.lib.util.Log +package io.ably.pubsub.liveobjects + +import io.ably.pubsub.liveobjects.message.WireObjectMessage +import io.ably.pubsub.liveobjects.message.WireObjectOperation +import io.ably.pubsub.liveobjects.message.WireObjectOperationAction +import io.ably.pubsub.liveobjects.message.WireObjectState +import io.ably.pubsub.liveobjects.message.WireObjectsMap +import io.ably.pubsub.liveobjects.value.BaseRealtimeObject +import io.ably.pubsub.liveobjects.value.ObjectUpdate +import io.ably.pubsub.liveobjects.value.noOp +import io.ably.pubsub.liveobjects.value.livecounter.InternalLiveCounter +import io.ably.pubsub.liveobjects.value.livemap.InternalLiveMap +import io.ably.pubsub.liveobjects.value.livemap.isEntryOrRefTombstoned +import io.ably.pubsub.util.Log /** * @spec RTO5 - Processes OBJECT and OBJECT_SYNC messages during sync sequences diff --git a/liveobjects/src/main/kotlin/io/ably/lib/liveobjects/ObjectsOperationSource.kt b/liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/ObjectsOperationSource.kt similarity index 83% rename from liveobjects/src/main/kotlin/io/ably/lib/liveobjects/ObjectsOperationSource.kt rename to liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/ObjectsOperationSource.kt index ac988fb96..009ea0283 100644 --- a/liveobjects/src/main/kotlin/io/ably/lib/liveobjects/ObjectsOperationSource.kt +++ b/liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/ObjectsOperationSource.kt @@ -1,4 +1,4 @@ -package io.ably.lib.liveobjects +package io.ably.pubsub.liveobjects /** @spec RTO22 */ internal enum class ObjectsOperationSource { diff --git a/liveobjects/src/main/kotlin/io/ably/lib/liveobjects/ObjectsPool.kt b/liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/ObjectsPool.kt similarity index 94% rename from liveobjects/src/main/kotlin/io/ably/lib/liveobjects/ObjectsPool.kt rename to liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/ObjectsPool.kt index 901b2a90f..1002d07ba 100644 --- a/liveobjects/src/main/kotlin/io/ably/lib/liveobjects/ObjectsPool.kt +++ b/liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/ObjectsPool.kt @@ -1,10 +1,10 @@ -package io.ably.lib.liveobjects +package io.ably.pubsub.liveobjects -import io.ably.lib.liveobjects.value.BaseRealtimeObject -import io.ably.lib.liveobjects.value.ObjectType -import io.ably.lib.liveobjects.value.livecounter.InternalLiveCounter -import io.ably.lib.liveobjects.value.livemap.InternalLiveMap -import io.ably.lib.util.Log +import io.ably.pubsub.liveobjects.value.BaseRealtimeObject +import io.ably.pubsub.liveobjects.value.ObjectType +import io.ably.pubsub.liveobjects.value.livecounter.InternalLiveCounter +import io.ably.pubsub.liveobjects.value.livemap.InternalLiveMap +import io.ably.pubsub.util.Log import kotlinx.coroutines.* import java.util.concurrent.ConcurrentHashMap diff --git a/liveobjects/src/main/kotlin/io/ably/lib/liveobjects/ObjectsState.kt b/liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/ObjectsState.kt similarity index 96% rename from liveobjects/src/main/kotlin/io/ably/lib/liveobjects/ObjectsState.kt rename to liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/ObjectsState.kt index 01cb056a4..0169ee035 100644 --- a/liveobjects/src/main/kotlin/io/ably/lib/liveobjects/ObjectsState.kt +++ b/liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/ObjectsState.kt @@ -1,12 +1,12 @@ -package io.ably.lib.liveobjects - -import io.ably.lib.liveobjects.state.ObjectStateChange -import io.ably.lib.liveobjects.state.ObjectStateEvent -import io.ably.lib.realtime.ChannelState -import io.ably.lib.types.AblyException -import io.ably.lib.types.ErrorInfo -import io.ably.lib.util.EventEmitter -import io.ably.lib.util.Log +package io.ably.pubsub.liveobjects + +import io.ably.pubsub.liveobjects.state.ObjectStateChange +import io.ably.pubsub.liveobjects.state.ObjectStateEvent +import io.ably.pubsub.realtime.ChannelState +import io.ably.pubsub.types.AblyException +import io.ably.pubsub.types.ErrorInfo +import io.ably.pubsub.util.EventEmitter +import io.ably.pubsub.util.Log import kotlinx.coroutines.* /** diff --git a/liveobjects/src/main/kotlin/io/ably/lib/liveobjects/ObjectsSyncTracker.kt b/liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/ObjectsSyncTracker.kt similarity index 99% rename from liveobjects/src/main/kotlin/io/ably/lib/liveobjects/ObjectsSyncTracker.kt rename to liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/ObjectsSyncTracker.kt index 32deb5522..645f474e3 100644 --- a/liveobjects/src/main/kotlin/io/ably/lib/liveobjects/ObjectsSyncTracker.kt +++ b/liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/ObjectsSyncTracker.kt @@ -1,4 +1,4 @@ -package io.ably.lib.liveobjects +package io.ably.pubsub.liveobjects /** * @spec RTO5 - SyncTracker class for tracking objects sync status diff --git a/liveobjects/src/main/kotlin/io/ably/lib/liveobjects/ServerTime.kt b/liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/ServerTime.kt similarity index 85% rename from liveobjects/src/main/kotlin/io/ably/lib/liveobjects/ServerTime.kt rename to liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/ServerTime.kt index 2fbeb1a28..830456035 100644 --- a/liveobjects/src/main/kotlin/io/ably/lib/liveobjects/ServerTime.kt +++ b/liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/ServerTime.kt @@ -1,8 +1,8 @@ -package io.ably.lib.liveobjects +package io.ably.pubsub.liveobjects -import io.ably.lib.liveobjects.adapter.AblyClientAdapter -import io.ably.lib.types.AblyException -import io.ably.lib.util.SystemClock +import io.ably.pubsub.liveobjects.adapter.AblyClientAdapter +import io.ably.pubsub.types.AblyException +import io.ably.pubsub.util.SystemClock import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.withLock diff --git a/liveobjects/src/main/kotlin/io/ably/lib/liveobjects/Utils.kt b/liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/Utils.kt similarity index 94% rename from liveobjects/src/main/kotlin/io/ably/lib/liveobjects/Utils.kt rename to liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/Utils.kt index accbafca4..9cdf28db0 100644 --- a/liveobjects/src/main/kotlin/io/ably/lib/liveobjects/Utils.kt +++ b/liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/Utils.kt @@ -1,7 +1,7 @@ -package io.ably.lib.liveobjects +package io.ably.pubsub.liveobjects -import io.ably.lib.types.AblyException -import io.ably.lib.types.ErrorInfo +import io.ably.pubsub.types.AblyException +import io.ably.pubsub.types.ErrorInfo import java.nio.charset.StandardCharsets internal fun ablyException( diff --git a/liveobjects/src/main/kotlin/io/ably/lib/liveobjects/instance/DefaultInstance.kt b/liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/instance/DefaultInstance.kt similarity index 69% rename from liveobjects/src/main/kotlin/io/ably/lib/liveobjects/instance/DefaultInstance.kt rename to liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/instance/DefaultInstance.kt index e85a53927..47ac8c882 100644 --- a/liveobjects/src/main/kotlin/io/ably/lib/liveobjects/instance/DefaultInstance.kt +++ b/liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/instance/DefaultInstance.kt @@ -1,25 +1,25 @@ -package io.ably.lib.liveobjects.instance +package io.ably.pubsub.liveobjects.instance -import io.ably.lib.liveobjects.DefaultRealtimeObject -import io.ably.lib.liveobjects.ValueType -import io.ably.lib.liveobjects.instance.types.BinaryInstance -import io.ably.lib.liveobjects.instance.types.BooleanInstance -import io.ably.lib.liveobjects.instance.types.DefaultBinaryInstance -import io.ably.lib.liveobjects.instance.types.DefaultBooleanInstance -import io.ably.lib.liveobjects.instance.types.DefaultJsonArrayInstance -import io.ably.lib.liveobjects.instance.types.DefaultJsonObjectInstance -import io.ably.lib.liveobjects.instance.types.DefaultLiveCounterInstance -import io.ably.lib.liveobjects.instance.types.DefaultLiveMapInstance -import io.ably.lib.liveobjects.instance.types.DefaultNumberInstance -import io.ably.lib.liveobjects.instance.types.DefaultStringInstance -import io.ably.lib.liveobjects.instance.types.JsonArrayInstance -import io.ably.lib.liveobjects.instance.types.JsonObjectInstance -import io.ably.lib.liveobjects.instance.types.LiveCounterInstance -import io.ably.lib.liveobjects.instance.types.LiveMapInstance -import io.ably.lib.liveobjects.instance.types.NumberInstance -import io.ably.lib.liveobjects.instance.types.StringInstance -import io.ably.lib.liveobjects.value.ResolvedValue -import io.ably.lib.liveobjects.value.valueType +import io.ably.pubsub.liveobjects.DefaultRealtimeObject +import io.ably.pubsub.liveobjects.ValueType +import io.ably.pubsub.liveobjects.instance.types.BinaryInstance +import io.ably.pubsub.liveobjects.instance.types.BooleanInstance +import io.ably.pubsub.liveobjects.instance.types.DefaultBinaryInstance +import io.ably.pubsub.liveobjects.instance.types.DefaultBooleanInstance +import io.ably.pubsub.liveobjects.instance.types.DefaultJsonArrayInstance +import io.ably.pubsub.liveobjects.instance.types.DefaultJsonObjectInstance +import io.ably.pubsub.liveobjects.instance.types.DefaultLiveCounterInstance +import io.ably.pubsub.liveobjects.instance.types.DefaultLiveMapInstance +import io.ably.pubsub.liveobjects.instance.types.DefaultNumberInstance +import io.ably.pubsub.liveobjects.instance.types.DefaultStringInstance +import io.ably.pubsub.liveobjects.instance.types.JsonArrayInstance +import io.ably.pubsub.liveobjects.instance.types.JsonObjectInstance +import io.ably.pubsub.liveobjects.instance.types.LiveCounterInstance +import io.ably.pubsub.liveobjects.instance.types.LiveMapInstance +import io.ably.pubsub.liveobjects.instance.types.NumberInstance +import io.ably.pubsub.liveobjects.instance.types.StringInstance +import io.ably.pubsub.liveobjects.value.ResolvedValue +import io.ably.pubsub.liveobjects.value.valueType import java.util.Base64 /** diff --git a/liveobjects/src/main/kotlin/io/ably/lib/liveobjects/instance/DefaultInstanceSubscriptionEvent.kt b/liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/instance/DefaultInstanceSubscriptionEvent.kt similarity index 75% rename from liveobjects/src/main/kotlin/io/ably/lib/liveobjects/instance/DefaultInstanceSubscriptionEvent.kt rename to liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/instance/DefaultInstanceSubscriptionEvent.kt index d1117b6f1..19c84bd8e 100644 --- a/liveobjects/src/main/kotlin/io/ably/lib/liveobjects/instance/DefaultInstanceSubscriptionEvent.kt +++ b/liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/instance/DefaultInstanceSubscriptionEvent.kt @@ -1,8 +1,8 @@ -package io.ably.lib.liveobjects.instance +package io.ably.pubsub.liveobjects.instance -import io.ably.lib.liveobjects.message.ObjectMessage -import io.ably.lib.liveobjects.value.livecounter.LiveCounterChangeEvent -import io.ably.lib.liveobjects.value.livemap.LiveMapChangeEvent +import io.ably.pubsub.liveobjects.message.ObjectMessage +import io.ably.pubsub.liveobjects.value.livecounter.LiveCounterChangeEvent +import io.ably.pubsub.liveobjects.value.livemap.LiveMapChangeEvent /** * Default implementation of [InstanceSubscriptionEvent], the event delivered to an diff --git a/liveobjects/src/main/kotlin/io/ably/lib/liveobjects/instance/types/DefaultBinaryInstance.kt b/liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/instance/types/DefaultBinaryInstance.kt similarity index 80% rename from liveobjects/src/main/kotlin/io/ably/lib/liveobjects/instance/types/DefaultBinaryInstance.kt rename to liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/instance/types/DefaultBinaryInstance.kt index 8265245e6..527bd05ed 100644 --- a/liveobjects/src/main/kotlin/io/ably/lib/liveobjects/instance/types/DefaultBinaryInstance.kt +++ b/liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/instance/types/DefaultBinaryInstance.kt @@ -1,9 +1,9 @@ -package io.ably.lib.liveobjects.instance.types +package io.ably.pubsub.liveobjects.instance.types import com.google.gson.JsonPrimitive -import io.ably.lib.liveobjects.DefaultRealtimeObject -import io.ably.lib.liveobjects.ValueType -import io.ably.lib.liveobjects.instance.DefaultInstance +import io.ably.pubsub.liveobjects.DefaultRealtimeObject +import io.ably.pubsub.liveobjects.ValueType +import io.ably.pubsub.liveobjects.instance.DefaultInstance import java.util.Base64 /** diff --git a/liveobjects/src/main/kotlin/io/ably/lib/liveobjects/instance/types/DefaultBooleanInstance.kt b/liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/instance/types/DefaultBooleanInstance.kt similarity index 78% rename from liveobjects/src/main/kotlin/io/ably/lib/liveobjects/instance/types/DefaultBooleanInstance.kt rename to liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/instance/types/DefaultBooleanInstance.kt index 7c59a81d0..411f65797 100644 --- a/liveobjects/src/main/kotlin/io/ably/lib/liveobjects/instance/types/DefaultBooleanInstance.kt +++ b/liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/instance/types/DefaultBooleanInstance.kt @@ -1,9 +1,9 @@ -package io.ably.lib.liveobjects.instance.types +package io.ably.pubsub.liveobjects.instance.types import com.google.gson.JsonPrimitive -import io.ably.lib.liveobjects.DefaultRealtimeObject -import io.ably.lib.liveobjects.ValueType -import io.ably.lib.liveobjects.instance.DefaultInstance +import io.ably.pubsub.liveobjects.DefaultRealtimeObject +import io.ably.pubsub.liveobjects.ValueType +import io.ably.pubsub.liveobjects.instance.DefaultInstance /** * Default implementation of [BooleanInstance], a read-only primitive view bound to its diff --git a/liveobjects/src/main/kotlin/io/ably/lib/liveobjects/instance/types/DefaultJsonArrayInstance.kt b/liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/instance/types/DefaultJsonArrayInstance.kt similarity index 78% rename from liveobjects/src/main/kotlin/io/ably/lib/liveobjects/instance/types/DefaultJsonArrayInstance.kt rename to liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/instance/types/DefaultJsonArrayInstance.kt index e94628b07..96452465e 100644 --- a/liveobjects/src/main/kotlin/io/ably/lib/liveobjects/instance/types/DefaultJsonArrayInstance.kt +++ b/liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/instance/types/DefaultJsonArrayInstance.kt @@ -1,9 +1,9 @@ -package io.ably.lib.liveobjects.instance.types +package io.ably.pubsub.liveobjects.instance.types import com.google.gson.JsonArray -import io.ably.lib.liveobjects.DefaultRealtimeObject -import io.ably.lib.liveobjects.ValueType -import io.ably.lib.liveobjects.instance.DefaultInstance +import io.ably.pubsub.liveobjects.DefaultRealtimeObject +import io.ably.pubsub.liveobjects.ValueType +import io.ably.pubsub.liveobjects.instance.DefaultInstance /** * Default implementation of [JsonArrayInstance], a read-only primitive view bound to its diff --git a/liveobjects/src/main/kotlin/io/ably/lib/liveobjects/instance/types/DefaultJsonObjectInstance.kt b/liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/instance/types/DefaultJsonObjectInstance.kt similarity index 78% rename from liveobjects/src/main/kotlin/io/ably/lib/liveobjects/instance/types/DefaultJsonObjectInstance.kt rename to liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/instance/types/DefaultJsonObjectInstance.kt index 8c6155770..e84fe1590 100644 --- a/liveobjects/src/main/kotlin/io/ably/lib/liveobjects/instance/types/DefaultJsonObjectInstance.kt +++ b/liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/instance/types/DefaultJsonObjectInstance.kt @@ -1,9 +1,9 @@ -package io.ably.lib.liveobjects.instance.types +package io.ably.pubsub.liveobjects.instance.types import com.google.gson.JsonObject -import io.ably.lib.liveobjects.DefaultRealtimeObject -import io.ably.lib.liveobjects.ValueType -import io.ably.lib.liveobjects.instance.DefaultInstance +import io.ably.pubsub.liveobjects.DefaultRealtimeObject +import io.ably.pubsub.liveobjects.ValueType +import io.ably.pubsub.liveobjects.instance.DefaultInstance /** * Default implementation of [JsonObjectInstance], a read-only primitive view bound to its diff --git a/liveobjects/src/main/kotlin/io/ably/lib/liveobjects/instance/types/DefaultLiveCounterInstance.kt b/liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/instance/types/DefaultLiveCounterInstance.kt similarity index 85% rename from liveobjects/src/main/kotlin/io/ably/lib/liveobjects/instance/types/DefaultLiveCounterInstance.kt rename to liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/instance/types/DefaultLiveCounterInstance.kt index b11b0e1b8..59747db54 100644 --- a/liveobjects/src/main/kotlin/io/ably/lib/liveobjects/instance/types/DefaultLiveCounterInstance.kt +++ b/liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/instance/types/DefaultLiveCounterInstance.kt @@ -1,12 +1,12 @@ -package io.ably.lib.liveobjects.instance.types +package io.ably.pubsub.liveobjects.instance.types import com.google.gson.JsonPrimitive -import io.ably.lib.liveobjects.DefaultRealtimeObject -import io.ably.lib.liveobjects.Subscription -import io.ably.lib.liveobjects.ValueType -import io.ably.lib.liveobjects.instance.DefaultInstance -import io.ably.lib.liveobjects.instance.InstanceListener -import io.ably.lib.liveobjects.value.livecounter.InternalLiveCounter +import io.ably.pubsub.liveobjects.DefaultRealtimeObject +import io.ably.pubsub.liveobjects.Subscription +import io.ably.pubsub.liveobjects.ValueType +import io.ably.pubsub.liveobjects.instance.DefaultInstance +import io.ably.pubsub.liveobjects.instance.InstanceListener +import io.ably.pubsub.liveobjects.value.livecounter.InternalLiveCounter import java.util.concurrent.CompletableFuture /** diff --git a/liveobjects/src/main/kotlin/io/ably/lib/liveobjects/instance/types/DefaultLiveMapInstance.kt b/liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/instance/types/DefaultLiveMapInstance.kt similarity index 85% rename from liveobjects/src/main/kotlin/io/ably/lib/liveobjects/instance/types/DefaultLiveMapInstance.kt rename to liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/instance/types/DefaultLiveMapInstance.kt index effe358e6..d8421c3a6 100644 --- a/liveobjects/src/main/kotlin/io/ably/lib/liveobjects/instance/types/DefaultLiveMapInstance.kt +++ b/liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/instance/types/DefaultLiveMapInstance.kt @@ -1,15 +1,15 @@ -package io.ably.lib.liveobjects.instance.types +package io.ably.pubsub.liveobjects.instance.types import com.google.gson.JsonObject -import io.ably.lib.liveobjects.DefaultRealtimeObject -import io.ably.lib.liveobjects.Subscription -import io.ably.lib.liveobjects.ValueType -import io.ably.lib.liveobjects.instance.DefaultInstance -import io.ably.lib.liveobjects.instance.Instance -import io.ably.lib.liveobjects.instance.InstanceListener -import io.ably.lib.liveobjects.instance.toInstance -import io.ably.lib.liveobjects.value.LiveMapValue -import io.ably.lib.liveobjects.value.livemap.InternalLiveMap +import io.ably.pubsub.liveobjects.DefaultRealtimeObject +import io.ably.pubsub.liveobjects.Subscription +import io.ably.pubsub.liveobjects.ValueType +import io.ably.pubsub.liveobjects.instance.DefaultInstance +import io.ably.pubsub.liveobjects.instance.Instance +import io.ably.pubsub.liveobjects.instance.InstanceListener +import io.ably.pubsub.liveobjects.instance.toInstance +import io.ably.pubsub.liveobjects.value.LiveMapValue +import io.ably.pubsub.liveobjects.value.livemap.InternalLiveMap import java.util.AbstractMap import java.util.concurrent.CompletableFuture diff --git a/liveobjects/src/main/kotlin/io/ably/lib/liveobjects/instance/types/DefaultNumberInstance.kt b/liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/instance/types/DefaultNumberInstance.kt similarity index 78% rename from liveobjects/src/main/kotlin/io/ably/lib/liveobjects/instance/types/DefaultNumberInstance.kt rename to liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/instance/types/DefaultNumberInstance.kt index 8da55d26e..ddc0f9482 100644 --- a/liveobjects/src/main/kotlin/io/ably/lib/liveobjects/instance/types/DefaultNumberInstance.kt +++ b/liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/instance/types/DefaultNumberInstance.kt @@ -1,9 +1,9 @@ -package io.ably.lib.liveobjects.instance.types +package io.ably.pubsub.liveobjects.instance.types import com.google.gson.JsonPrimitive -import io.ably.lib.liveobjects.DefaultRealtimeObject -import io.ably.lib.liveobjects.ValueType -import io.ably.lib.liveobjects.instance.DefaultInstance +import io.ably.pubsub.liveobjects.DefaultRealtimeObject +import io.ably.pubsub.liveobjects.ValueType +import io.ably.pubsub.liveobjects.instance.DefaultInstance /** * Default implementation of [NumberInstance], a read-only primitive view bound to its diff --git a/liveobjects/src/main/kotlin/io/ably/lib/liveobjects/instance/types/DefaultStringInstance.kt b/liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/instance/types/DefaultStringInstance.kt similarity index 78% rename from liveobjects/src/main/kotlin/io/ably/lib/liveobjects/instance/types/DefaultStringInstance.kt rename to liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/instance/types/DefaultStringInstance.kt index 19efc683f..ce0f92a9b 100644 --- a/liveobjects/src/main/kotlin/io/ably/lib/liveobjects/instance/types/DefaultStringInstance.kt +++ b/liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/instance/types/DefaultStringInstance.kt @@ -1,9 +1,9 @@ -package io.ably.lib.liveobjects.instance.types +package io.ably.pubsub.liveobjects.instance.types import com.google.gson.JsonPrimitive -import io.ably.lib.liveobjects.DefaultRealtimeObject -import io.ably.lib.liveobjects.ValueType -import io.ably.lib.liveobjects.instance.DefaultInstance +import io.ably.pubsub.liveobjects.DefaultRealtimeObject +import io.ably.pubsub.liveobjects.ValueType +import io.ably.pubsub.liveobjects.instance.DefaultInstance /** * Default implementation of [StringInstance], a read-only primitive view bound to its diff --git a/liveobjects/src/main/kotlin/io/ably/lib/liveobjects/message/DefaultObjectMessage.kt b/liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/message/DefaultObjectMessage.kt similarity index 98% rename from liveobjects/src/main/kotlin/io/ably/lib/liveobjects/message/DefaultObjectMessage.kt rename to liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/message/DefaultObjectMessage.kt index b085e8a7e..07f40d12b 100644 --- a/liveobjects/src/main/kotlin/io/ably/lib/liveobjects/message/DefaultObjectMessage.kt +++ b/liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/message/DefaultObjectMessage.kt @@ -1,8 +1,8 @@ -package io.ably.lib.liveobjects.message +package io.ably.pubsub.liveobjects.message import com.google.gson.JsonElement import com.google.gson.JsonObject -import io.ably.lib.liveobjects.objectStateError +import io.ably.pubsub.liveobjects.objectStateError import java.util.* /** diff --git a/liveobjects/src/main/kotlin/io/ably/lib/liveobjects/message/WireObjectMessage.kt b/liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/message/WireObjectMessage.kt similarity index 95% rename from liveobjects/src/main/kotlin/io/ably/lib/liveobjects/message/WireObjectMessage.kt rename to liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/message/WireObjectMessage.kt index a004a9aeb..98ade97c0 100644 --- a/liveobjects/src/main/kotlin/io/ably/lib/liveobjects/message/WireObjectMessage.kt +++ b/liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/message/WireObjectMessage.kt @@ -1,4 +1,4 @@ -package io.ably.lib.liveobjects.message +package io.ably.pubsub.liveobjects.message import com.google.gson.JsonElement import com.google.gson.JsonNull @@ -6,18 +6,18 @@ import com.google.gson.JsonObject import com.google.gson.JsonPrimitive import com.google.gson.annotations.JsonAdapter import com.google.gson.annotations.SerializedName -import io.ably.lib.liveobjects.byteSize -import io.ably.lib.liveobjects.serialization.WireObjectDataJsonSerializer -import io.ably.lib.liveobjects.serialization.gson +import io.ably.pubsub.liveobjects.byteSize +import io.ably.pubsub.liveobjects.serialization.WireObjectDataJsonSerializer +import io.ably.pubsub.liveobjects.serialization.gson import java.util.Base64 /** * Wire-level object model for the path-based public API implementation. * - * Copied from the legacy internal model (`io.ably.lib.objects.ObjectMessage`) - * so that this package has no dependency on `io.ably.lib.objects`. The `Wire` + * Copied from the legacy internal model (`io.ably.pubsub.objects.ObjectMessage`) + * so that this package has no dependency on `io.ably.pubsub.objects`. The `Wire` * prefix distinguishes these internal carriers from the public interfaces in - * `io.ably.lib.object.message`. + * `io.ably.pubsub.object.message`. * * Spec: OM*, OOP*, OD*, MCR*, MST*, MRM*, CCR*, CIN*, ODE*, MCL*, OME*, MCRO*, CCRO*, OMP*, OCN*, OST* */ diff --git a/liveobjects/src/main/kotlin/io/ably/lib/liveobjects/path/DefaultPathObject.kt b/liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/path/DefaultPathObject.kt similarity index 72% rename from liveobjects/src/main/kotlin/io/ably/lib/liveobjects/path/DefaultPathObject.kt rename to liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/path/DefaultPathObject.kt index d7e5266a6..418f6247f 100644 --- a/liveobjects/src/main/kotlin/io/ably/lib/liveobjects/path/DefaultPathObject.kt +++ b/liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/path/DefaultPathObject.kt @@ -1,33 +1,33 @@ -package io.ably.lib.liveobjects.path +package io.ably.pubsub.liveobjects.path import com.google.gson.JsonElement import com.google.gson.JsonPrimitive -import io.ably.lib.liveobjects.DefaultRealtimeObject -import io.ably.lib.liveobjects.ROOT_OBJECT_ID -import io.ably.lib.liveobjects.Subscription -import io.ably.lib.liveobjects.ValueType -import io.ably.lib.liveobjects.instance.Instance -import io.ably.lib.liveobjects.instance.toInstance -import io.ably.lib.liveobjects.path.types.BinaryPathObject -import io.ably.lib.liveobjects.path.types.BooleanPathObject -import io.ably.lib.liveobjects.path.types.DefaultBinaryPathObject -import io.ably.lib.liveobjects.path.types.DefaultBooleanPathObject -import io.ably.lib.liveobjects.path.types.DefaultJsonArrayPathObject -import io.ably.lib.liveobjects.path.types.DefaultJsonObjectPathObject -import io.ably.lib.liveobjects.path.types.DefaultLiveCounterPathObject -import io.ably.lib.liveobjects.path.types.DefaultLiveMapPathObject -import io.ably.lib.liveobjects.path.types.DefaultNumberPathObject -import io.ably.lib.liveobjects.path.types.DefaultStringPathObject -import io.ably.lib.liveobjects.path.types.JsonArrayPathObject -import io.ably.lib.liveobjects.path.types.JsonObjectPathObject -import io.ably.lib.liveobjects.path.types.LiveCounterPathObject -import io.ably.lib.liveobjects.path.types.LiveMapPathObject -import io.ably.lib.liveobjects.path.types.NumberPathObject -import io.ably.lib.liveobjects.path.types.StringPathObject -import io.ably.lib.liveobjects.value.ResolvedValue -import io.ably.lib.liveobjects.value.livemap.InternalLiveMap -import io.ably.lib.liveobjects.message.toCompactJsonElement -import io.ably.lib.liveobjects.value.valueType +import io.ably.pubsub.liveobjects.DefaultRealtimeObject +import io.ably.pubsub.liveobjects.ROOT_OBJECT_ID +import io.ably.pubsub.liveobjects.Subscription +import io.ably.pubsub.liveobjects.ValueType +import io.ably.pubsub.liveobjects.instance.Instance +import io.ably.pubsub.liveobjects.instance.toInstance +import io.ably.pubsub.liveobjects.path.types.BinaryPathObject +import io.ably.pubsub.liveobjects.path.types.BooleanPathObject +import io.ably.pubsub.liveobjects.path.types.DefaultBinaryPathObject +import io.ably.pubsub.liveobjects.path.types.DefaultBooleanPathObject +import io.ably.pubsub.liveobjects.path.types.DefaultJsonArrayPathObject +import io.ably.pubsub.liveobjects.path.types.DefaultJsonObjectPathObject +import io.ably.pubsub.liveobjects.path.types.DefaultLiveCounterPathObject +import io.ably.pubsub.liveobjects.path.types.DefaultLiveMapPathObject +import io.ably.pubsub.liveobjects.path.types.DefaultNumberPathObject +import io.ably.pubsub.liveobjects.path.types.DefaultStringPathObject +import io.ably.pubsub.liveobjects.path.types.JsonArrayPathObject +import io.ably.pubsub.liveobjects.path.types.JsonObjectPathObject +import io.ably.pubsub.liveobjects.path.types.LiveCounterPathObject +import io.ably.pubsub.liveobjects.path.types.LiveMapPathObject +import io.ably.pubsub.liveobjects.path.types.NumberPathObject +import io.ably.pubsub.liveobjects.path.types.StringPathObject +import io.ably.pubsub.liveobjects.value.ResolvedValue +import io.ably.pubsub.liveobjects.value.livemap.InternalLiveMap +import io.ably.pubsub.liveobjects.message.toCompactJsonElement +import io.ably.pubsub.liveobjects.value.valueType /** * Default implementation of [PathObject], the untyped node in the path-addressed view of diff --git a/liveobjects/src/main/kotlin/io/ably/lib/liveobjects/path/DefaultPathObjectSubscriptionEvent.kt b/liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/path/DefaultPathObjectSubscriptionEvent.kt similarity index 85% rename from liveobjects/src/main/kotlin/io/ably/lib/liveobjects/path/DefaultPathObjectSubscriptionEvent.kt rename to liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/path/DefaultPathObjectSubscriptionEvent.kt index 17e474807..10bb09581 100644 --- a/liveobjects/src/main/kotlin/io/ably/lib/liveobjects/path/DefaultPathObjectSubscriptionEvent.kt +++ b/liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/path/DefaultPathObjectSubscriptionEvent.kt @@ -1,6 +1,6 @@ -package io.ably.lib.liveobjects.path +package io.ably.pubsub.liveobjects.path -import io.ably.lib.liveobjects.message.ObjectMessage +import io.ably.pubsub.liveobjects.message.ObjectMessage /** * Default implementation of [PathObjectSubscriptionEvent], the event delivered to a diff --git a/liveobjects/src/main/kotlin/io/ably/lib/liveobjects/path/PathObjectSubscriptionRegister.kt b/liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/path/PathObjectSubscriptionRegister.kt similarity index 92% rename from liveobjects/src/main/kotlin/io/ably/lib/liveobjects/path/PathObjectSubscriptionRegister.kt rename to liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/path/PathObjectSubscriptionRegister.kt index 245ff7a25..1ab01e65c 100644 --- a/liveobjects/src/main/kotlin/io/ably/lib/liveobjects/path/PathObjectSubscriptionRegister.kt +++ b/liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/path/PathObjectSubscriptionRegister.kt @@ -1,11 +1,11 @@ -package io.ably.lib.liveobjects.path +package io.ably.pubsub.liveobjects.path -import io.ably.lib.liveobjects.DefaultRealtimeObject -import io.ably.lib.liveobjects.Subscription -import io.ably.lib.liveobjects.message.ObjectMessage -import io.ably.lib.liveobjects.onceSubscription -import io.ably.lib.util.EventEmitter -import io.ably.lib.util.Log +import io.ably.pubsub.liveobjects.DefaultRealtimeObject +import io.ably.pubsub.liveobjects.Subscription +import io.ably.pubsub.liveobjects.message.ObjectMessage +import io.ably.pubsub.liveobjects.onceSubscription +import io.ably.pubsub.util.EventEmitter +import io.ably.pubsub.util.Log /** * Registry for PathObject subscriptions and path-event dispatch. One per RealtimeObject. diff --git a/liveobjects/src/main/kotlin/io/ably/lib/liveobjects/path/PathSegments.kt b/liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/path/PathSegments.kt similarity index 98% rename from liveobjects/src/main/kotlin/io/ably/lib/liveobjects/path/PathSegments.kt rename to liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/path/PathSegments.kt index 37169a447..e48359205 100644 --- a/liveobjects/src/main/kotlin/io/ably/lib/liveobjects/path/PathSegments.kt +++ b/liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/path/PathSegments.kt @@ -1,4 +1,4 @@ -package io.ably.lib.liveobjects.path +package io.ably.pubsub.liveobjects.path /** * Dot-delimited path <-> segment list conversions. A dot inside a segment is escaped as `\.` diff --git a/liveobjects/src/main/kotlin/io/ably/lib/liveobjects/path/types/DefaultBinaryPathObject.kt b/liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/path/types/DefaultBinaryPathObject.kt similarity index 69% rename from liveobjects/src/main/kotlin/io/ably/lib/liveobjects/path/types/DefaultBinaryPathObject.kt rename to liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/path/types/DefaultBinaryPathObject.kt index baf2fa850..fb4e8c97b 100644 --- a/liveobjects/src/main/kotlin/io/ably/lib/liveobjects/path/types/DefaultBinaryPathObject.kt +++ b/liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/path/types/DefaultBinaryPathObject.kt @@ -1,10 +1,10 @@ -package io.ably.lib.liveobjects.path.types +package io.ably.pubsub.liveobjects.path.types -import io.ably.lib.liveobjects.DefaultRealtimeObject -import io.ably.lib.liveobjects.ValueType -import io.ably.lib.liveobjects.path.DefaultPathObject -import io.ably.lib.liveobjects.value.ResolvedValue -import io.ably.lib.liveobjects.value.valueType +import io.ably.pubsub.liveobjects.DefaultRealtimeObject +import io.ably.pubsub.liveobjects.ValueType +import io.ably.pubsub.liveobjects.path.DefaultPathObject +import io.ably.pubsub.liveobjects.value.ResolvedValue +import io.ably.pubsub.liveobjects.value.valueType import java.util.Base64 /** diff --git a/liveobjects/src/main/kotlin/io/ably/lib/liveobjects/path/types/DefaultBooleanPathObject.kt b/liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/path/types/DefaultBooleanPathObject.kt similarity index 66% rename from liveobjects/src/main/kotlin/io/ably/lib/liveobjects/path/types/DefaultBooleanPathObject.kt rename to liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/path/types/DefaultBooleanPathObject.kt index bdd69d68e..84d5e563a 100644 --- a/liveobjects/src/main/kotlin/io/ably/lib/liveobjects/path/types/DefaultBooleanPathObject.kt +++ b/liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/path/types/DefaultBooleanPathObject.kt @@ -1,10 +1,10 @@ -package io.ably.lib.liveobjects.path.types +package io.ably.pubsub.liveobjects.path.types -import io.ably.lib.liveobjects.DefaultRealtimeObject -import io.ably.lib.liveobjects.ValueType -import io.ably.lib.liveobjects.path.DefaultPathObject -import io.ably.lib.liveobjects.value.ResolvedValue -import io.ably.lib.liveobjects.value.valueType +import io.ably.pubsub.liveobjects.DefaultRealtimeObject +import io.ably.pubsub.liveobjects.ValueType +import io.ably.pubsub.liveobjects.path.DefaultPathObject +import io.ably.pubsub.liveobjects.value.ResolvedValue +import io.ably.pubsub.liveobjects.value.valueType /** * Default implementation of [BooleanPathObject], a terminal primitive view that only adds a diff --git a/liveobjects/src/main/kotlin/io/ably/lib/liveobjects/path/types/DefaultJsonArrayPathObject.kt b/liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/path/types/DefaultJsonArrayPathObject.kt similarity index 68% rename from liveobjects/src/main/kotlin/io/ably/lib/liveobjects/path/types/DefaultJsonArrayPathObject.kt rename to liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/path/types/DefaultJsonArrayPathObject.kt index 86fce1ad6..fae3b09c2 100644 --- a/liveobjects/src/main/kotlin/io/ably/lib/liveobjects/path/types/DefaultJsonArrayPathObject.kt +++ b/liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/path/types/DefaultJsonArrayPathObject.kt @@ -1,11 +1,11 @@ -package io.ably.lib.liveobjects.path.types +package io.ably.pubsub.liveobjects.path.types import com.google.gson.JsonArray -import io.ably.lib.liveobjects.DefaultRealtimeObject -import io.ably.lib.liveobjects.ValueType -import io.ably.lib.liveobjects.path.DefaultPathObject -import io.ably.lib.liveobjects.value.ResolvedValue -import io.ably.lib.liveobjects.value.valueType +import io.ably.pubsub.liveobjects.DefaultRealtimeObject +import io.ably.pubsub.liveobjects.ValueType +import io.ably.pubsub.liveobjects.path.DefaultPathObject +import io.ably.pubsub.liveobjects.value.ResolvedValue +import io.ably.pubsub.liveobjects.value.valueType /** * Default implementation of [JsonArrayPathObject], a terminal primitive view that only adds diff --git a/liveobjects/src/main/kotlin/io/ably/lib/liveobjects/path/types/DefaultJsonObjectPathObject.kt b/liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/path/types/DefaultJsonObjectPathObject.kt similarity index 68% rename from liveobjects/src/main/kotlin/io/ably/lib/liveobjects/path/types/DefaultJsonObjectPathObject.kt rename to liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/path/types/DefaultJsonObjectPathObject.kt index 567f0f3c6..4f1312066 100644 --- a/liveobjects/src/main/kotlin/io/ably/lib/liveobjects/path/types/DefaultJsonObjectPathObject.kt +++ b/liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/path/types/DefaultJsonObjectPathObject.kt @@ -1,11 +1,11 @@ -package io.ably.lib.liveobjects.path.types +package io.ably.pubsub.liveobjects.path.types import com.google.gson.JsonObject -import io.ably.lib.liveobjects.DefaultRealtimeObject -import io.ably.lib.liveobjects.ValueType -import io.ably.lib.liveobjects.path.DefaultPathObject -import io.ably.lib.liveobjects.value.ResolvedValue -import io.ably.lib.liveobjects.value.valueType +import io.ably.pubsub.liveobjects.DefaultRealtimeObject +import io.ably.pubsub.liveobjects.ValueType +import io.ably.pubsub.liveobjects.path.DefaultPathObject +import io.ably.pubsub.liveobjects.value.ResolvedValue +import io.ably.pubsub.liveobjects.value.valueType /** * Default implementation of [JsonObjectPathObject], a terminal primitive view that only adds diff --git a/liveobjects/src/main/kotlin/io/ably/lib/liveobjects/path/types/DefaultLiveCounterPathObject.kt b/liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/path/types/DefaultLiveCounterPathObject.kt similarity index 86% rename from liveobjects/src/main/kotlin/io/ably/lib/liveobjects/path/types/DefaultLiveCounterPathObject.kt rename to liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/path/types/DefaultLiveCounterPathObject.kt index 5c3606426..84584a1f1 100644 --- a/liveobjects/src/main/kotlin/io/ably/lib/liveobjects/path/types/DefaultLiveCounterPathObject.kt +++ b/liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/path/types/DefaultLiveCounterPathObject.kt @@ -1,10 +1,10 @@ -package io.ably.lib.liveobjects.path.types +package io.ably.pubsub.liveobjects.path.types -import io.ably.lib.liveobjects.DefaultRealtimeObject -import io.ably.lib.liveobjects.path.DefaultPathObject -import io.ably.lib.liveobjects.pathNotResolvedError -import io.ably.lib.liveobjects.typeMismatchError -import io.ably.lib.liveobjects.value.ResolvedValue +import io.ably.pubsub.liveobjects.DefaultRealtimeObject +import io.ably.pubsub.liveobjects.path.DefaultPathObject +import io.ably.pubsub.liveobjects.pathNotResolvedError +import io.ably.pubsub.liveobjects.typeMismatchError +import io.ably.pubsub.liveobjects.value.ResolvedValue import java.util.concurrent.CompletableFuture /** diff --git a/liveobjects/src/main/kotlin/io/ably/lib/liveobjects/path/types/DefaultLiveMapPathObject.kt b/liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/path/types/DefaultLiveMapPathObject.kt similarity index 87% rename from liveobjects/src/main/kotlin/io/ably/lib/liveobjects/path/types/DefaultLiveMapPathObject.kt rename to liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/path/types/DefaultLiveMapPathObject.kt index 96e5ae458..c549287a0 100644 --- a/liveobjects/src/main/kotlin/io/ably/lib/liveobjects/path/types/DefaultLiveMapPathObject.kt +++ b/liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/path/types/DefaultLiveMapPathObject.kt @@ -1,13 +1,13 @@ -package io.ably.lib.liveobjects.path.types +package io.ably.pubsub.liveobjects.path.types -import io.ably.lib.liveobjects.DefaultRealtimeObject -import io.ably.lib.liveobjects.path.DefaultPathObject -import io.ably.lib.liveobjects.path.PathObject -import io.ably.lib.liveobjects.path.PathSegments -import io.ably.lib.liveobjects.pathNotResolvedError -import io.ably.lib.liveobjects.typeMismatchError -import io.ably.lib.liveobjects.value.LiveMapValue -import io.ably.lib.liveobjects.value.ResolvedValue +import io.ably.pubsub.liveobjects.DefaultRealtimeObject +import io.ably.pubsub.liveobjects.path.DefaultPathObject +import io.ably.pubsub.liveobjects.path.PathObject +import io.ably.pubsub.liveobjects.path.PathSegments +import io.ably.pubsub.liveobjects.pathNotResolvedError +import io.ably.pubsub.liveobjects.typeMismatchError +import io.ably.pubsub.liveobjects.value.LiveMapValue +import io.ably.pubsub.liveobjects.value.ResolvedValue import java.util.AbstractMap import java.util.concurrent.CompletableFuture diff --git a/liveobjects/src/main/kotlin/io/ably/lib/liveobjects/path/types/DefaultNumberPathObject.kt b/liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/path/types/DefaultNumberPathObject.kt similarity index 66% rename from liveobjects/src/main/kotlin/io/ably/lib/liveobjects/path/types/DefaultNumberPathObject.kt rename to liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/path/types/DefaultNumberPathObject.kt index 005fb877c..a09647a95 100644 --- a/liveobjects/src/main/kotlin/io/ably/lib/liveobjects/path/types/DefaultNumberPathObject.kt +++ b/liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/path/types/DefaultNumberPathObject.kt @@ -1,10 +1,10 @@ -package io.ably.lib.liveobjects.path.types +package io.ably.pubsub.liveobjects.path.types -import io.ably.lib.liveobjects.DefaultRealtimeObject -import io.ably.lib.liveobjects.ValueType -import io.ably.lib.liveobjects.path.DefaultPathObject -import io.ably.lib.liveobjects.value.ResolvedValue -import io.ably.lib.liveobjects.value.valueType +import io.ably.pubsub.liveobjects.DefaultRealtimeObject +import io.ably.pubsub.liveobjects.ValueType +import io.ably.pubsub.liveobjects.path.DefaultPathObject +import io.ably.pubsub.liveobjects.value.ResolvedValue +import io.ably.pubsub.liveobjects.value.valueType /** * Default implementation of [NumberPathObject], a terminal primitive view that only adds a diff --git a/liveobjects/src/main/kotlin/io/ably/lib/liveobjects/path/types/DefaultStringPathObject.kt b/liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/path/types/DefaultStringPathObject.kt similarity index 66% rename from liveobjects/src/main/kotlin/io/ably/lib/liveobjects/path/types/DefaultStringPathObject.kt rename to liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/path/types/DefaultStringPathObject.kt index add069e42..a61a4fadd 100644 --- a/liveobjects/src/main/kotlin/io/ably/lib/liveobjects/path/types/DefaultStringPathObject.kt +++ b/liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/path/types/DefaultStringPathObject.kt @@ -1,10 +1,10 @@ -package io.ably.lib.liveobjects.path.types +package io.ably.pubsub.liveobjects.path.types -import io.ably.lib.liveobjects.DefaultRealtimeObject -import io.ably.lib.liveobjects.ValueType -import io.ably.lib.liveobjects.path.DefaultPathObject -import io.ably.lib.liveobjects.value.ResolvedValue -import io.ably.lib.liveobjects.value.valueType +import io.ably.pubsub.liveobjects.DefaultRealtimeObject +import io.ably.pubsub.liveobjects.ValueType +import io.ably.pubsub.liveobjects.path.DefaultPathObject +import io.ably.pubsub.liveobjects.value.ResolvedValue +import io.ably.pubsub.liveobjects.value.valueType /** * Default implementation of [StringPathObject], a terminal primitive view that only adds a diff --git a/liveobjects/src/main/kotlin/io/ably/lib/liveobjects/serialization/DefaultSerialization.kt b/liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/serialization/DefaultSerialization.kt similarity index 93% rename from liveobjects/src/main/kotlin/io/ably/lib/liveobjects/serialization/DefaultSerialization.kt rename to liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/serialization/DefaultSerialization.kt index 7deb4fe24..42989bff8 100644 --- a/liveobjects/src/main/kotlin/io/ably/lib/liveobjects/serialization/DefaultSerialization.kt +++ b/liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/serialization/DefaultSerialization.kt @@ -1,7 +1,7 @@ -package io.ably.lib.liveobjects.serialization +package io.ably.pubsub.liveobjects.serialization import com.google.gson.* -import io.ably.lib.liveobjects.message.WireObjectMessage +import io.ably.pubsub.liveobjects.message.WireObjectMessage import org.msgpack.core.MessagePacker import org.msgpack.core.MessageUnpacker diff --git a/liveobjects/src/main/kotlin/io/ably/lib/liveobjects/serialization/JsonSerialization.kt b/liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/serialization/JsonSerialization.kt similarity index 91% rename from liveobjects/src/main/kotlin/io/ably/lib/liveobjects/serialization/JsonSerialization.kt rename to liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/serialization/JsonSerialization.kt index 3620dfee9..55786f0ff 100644 --- a/liveobjects/src/main/kotlin/io/ably/lib/liveobjects/serialization/JsonSerialization.kt +++ b/liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/serialization/JsonSerialization.kt @@ -1,10 +1,10 @@ -package io.ably.lib.liveobjects.serialization +package io.ably.pubsub.liveobjects.serialization import com.google.gson.* -import io.ably.lib.liveobjects.message.WireObjectData -import io.ably.lib.liveobjects.message.WireObjectMessage -import io.ably.lib.liveobjects.message.WireObjectOperationAction -import io.ably.lib.liveobjects.message.WireObjectsMapSemantics +import io.ably.pubsub.liveobjects.message.WireObjectData +import io.ably.pubsub.liveobjects.message.WireObjectMessage +import io.ably.pubsub.liveobjects.message.WireObjectOperationAction +import io.ably.pubsub.liveobjects.message.WireObjectsMapSemantics import java.lang.reflect.Type import kotlin.enums.EnumEntries diff --git a/liveobjects/src/main/kotlin/io/ably/lib/liveobjects/serialization/MsgpackSerialization.kt b/liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/serialization/MsgpackSerialization.kt similarity index 95% rename from liveobjects/src/main/kotlin/io/ably/lib/liveobjects/serialization/MsgpackSerialization.kt rename to liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/serialization/MsgpackSerialization.kt index 85e4a6270..a24cef20c 100644 --- a/liveobjects/src/main/kotlin/io/ably/lib/liveobjects/serialization/MsgpackSerialization.kt +++ b/liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/serialization/MsgpackSerialization.kt @@ -1,28 +1,28 @@ -package io.ably.lib.liveobjects.serialization +package io.ably.pubsub.liveobjects.serialization import com.google.gson.JsonElement import com.google.gson.JsonObject import com.google.gson.JsonParser -import io.ably.lib.liveobjects.message.WireCounterCreate -import io.ably.lib.liveobjects.message.WireCounterCreateWithObjectId -import io.ably.lib.liveobjects.message.WireCounterInc -import io.ably.lib.liveobjects.message.WireMapClear -import io.ably.lib.liveobjects.message.WireMapCreate -import io.ably.lib.liveobjects.message.WireMapCreateWithObjectId -import io.ably.lib.liveobjects.message.WireMapRemove -import io.ably.lib.liveobjects.message.WireMapSet -import io.ably.lib.liveobjects.message.WireObjectData -import io.ably.lib.liveobjects.message.WireObjectDelete -import io.ably.lib.liveobjects.message.WireObjectMessage -import io.ably.lib.liveobjects.message.WireObjectOperation -import io.ably.lib.liveobjects.message.WireObjectOperationAction -import io.ably.lib.liveobjects.message.WireObjectState -import io.ably.lib.liveobjects.message.WireObjectsCounter -import io.ably.lib.liveobjects.message.WireObjectsMap -import io.ably.lib.liveobjects.message.WireObjectsMapEntry -import io.ably.lib.liveobjects.message.WireObjectsMapSemantics -import io.ably.lib.liveobjects.objectStateError -import io.ably.lib.util.Serialisation +import io.ably.pubsub.liveobjects.message.WireCounterCreate +import io.ably.pubsub.liveobjects.message.WireCounterCreateWithObjectId +import io.ably.pubsub.liveobjects.message.WireCounterInc +import io.ably.pubsub.liveobjects.message.WireMapClear +import io.ably.pubsub.liveobjects.message.WireMapCreate +import io.ably.pubsub.liveobjects.message.WireMapCreateWithObjectId +import io.ably.pubsub.liveobjects.message.WireMapRemove +import io.ably.pubsub.liveobjects.message.WireMapSet +import io.ably.pubsub.liveobjects.message.WireObjectData +import io.ably.pubsub.liveobjects.message.WireObjectDelete +import io.ably.pubsub.liveobjects.message.WireObjectMessage +import io.ably.pubsub.liveobjects.message.WireObjectOperation +import io.ably.pubsub.liveobjects.message.WireObjectOperationAction +import io.ably.pubsub.liveobjects.message.WireObjectState +import io.ably.pubsub.liveobjects.message.WireObjectsCounter +import io.ably.pubsub.liveobjects.message.WireObjectsMap +import io.ably.pubsub.liveobjects.message.WireObjectsMapEntry +import io.ably.pubsub.liveobjects.message.WireObjectsMapSemantics +import io.ably.pubsub.liveobjects.objectStateError +import io.ably.pubsub.util.Serialisation import java.util.Base64 import org.msgpack.core.MessageFormat import org.msgpack.core.MessagePacker diff --git a/liveobjects/src/main/kotlin/io/ably/lib/liveobjects/value/BaseRealtimeLiveObject.kt b/liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/value/BaseRealtimeLiveObject.kt similarity index 95% rename from liveobjects/src/main/kotlin/io/ably/lib/liveobjects/value/BaseRealtimeLiveObject.kt rename to liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/value/BaseRealtimeLiveObject.kt index 3a1ff20f8..fb9a31573 100644 --- a/liveobjects/src/main/kotlin/io/ably/lib/liveobjects/value/BaseRealtimeLiveObject.kt +++ b/liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/value/BaseRealtimeLiveObject.kt @@ -1,18 +1,18 @@ -package io.ably.lib.liveobjects.value - -import io.ably.lib.liveobjects.DefaultRealtimeObject -import io.ably.lib.liveobjects.ObjectsOperationSource -import io.ably.lib.liveobjects.ObjectsPool -import io.ably.lib.liveobjects.ROOT_OBJECT_ID -import io.ably.lib.liveobjects.message.ObjectMessage -import io.ably.lib.liveobjects.message.WireObjectMessage -import io.ably.lib.liveobjects.message.WireObjectOperation -import io.ably.lib.liveobjects.message.WireObjectState -import io.ably.lib.liveobjects.message.toPublicMessage -import io.ably.lib.liveobjects.objectError -import io.ably.lib.liveobjects.value.livemap.InternalLiveMap -import io.ably.lib.util.Clock -import io.ably.lib.util.Log +package io.ably.pubsub.liveobjects.value + +import io.ably.pubsub.liveobjects.DefaultRealtimeObject +import io.ably.pubsub.liveobjects.ObjectsOperationSource +import io.ably.pubsub.liveobjects.ObjectsPool +import io.ably.pubsub.liveobjects.ROOT_OBJECT_ID +import io.ably.pubsub.liveobjects.message.ObjectMessage +import io.ably.pubsub.liveobjects.message.WireObjectMessage +import io.ably.pubsub.liveobjects.message.WireObjectOperation +import io.ably.pubsub.liveobjects.message.WireObjectState +import io.ably.pubsub.liveobjects.message.toPublicMessage +import io.ably.pubsub.liveobjects.objectError +import io.ably.pubsub.liveobjects.value.livemap.InternalLiveMap +import io.ably.pubsub.util.Clock +import io.ably.pubsub.util.Log internal enum class ObjectType(val value: String) { Map("map"), diff --git a/liveobjects/src/main/kotlin/io/ably/lib/liveobjects/value/ObjectUpdate.kt b/liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/value/ObjectUpdate.kt similarity index 88% rename from liveobjects/src/main/kotlin/io/ably/lib/liveobjects/value/ObjectUpdate.kt rename to liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/value/ObjectUpdate.kt index 9a972e3f4..c84ddf7a0 100644 --- a/liveobjects/src/main/kotlin/io/ably/lib/liveobjects/value/ObjectUpdate.kt +++ b/liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/value/ObjectUpdate.kt @@ -1,7 +1,7 @@ -package io.ably.lib.liveobjects.value +package io.ably.pubsub.liveobjects.value -import io.ably.lib.liveobjects.message.WireObjectMessage -import io.ably.lib.liveobjects.value.livemap.MapChange +import io.ably.pubsub.liveobjects.message.WireObjectMessage +import io.ably.pubsub.liveobjects.value.livemap.MapChange /** * An update emitted for a LiveObject data change. Spec: RTLO4b4 (LiveObjectUpdate) diff --git a/liveobjects/src/main/kotlin/io/ably/lib/liveobjects/value/ResolvedValue.kt b/liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/value/ResolvedValue.kt similarity index 83% rename from liveobjects/src/main/kotlin/io/ably/lib/liveobjects/value/ResolvedValue.kt rename to liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/value/ResolvedValue.kt index a7c930fce..fc5601885 100644 --- a/liveobjects/src/main/kotlin/io/ably/lib/liveobjects/value/ResolvedValue.kt +++ b/liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/value/ResolvedValue.kt @@ -1,9 +1,9 @@ -package io.ably.lib.liveobjects.value +package io.ably.pubsub.liveobjects.value -import io.ably.lib.liveobjects.ValueType -import io.ably.lib.liveobjects.message.WireObjectData -import io.ably.lib.liveobjects.value.livecounter.InternalLiveCounter -import io.ably.lib.liveobjects.value.livemap.InternalLiveMap +import io.ably.pubsub.liveobjects.ValueType +import io.ably.pubsub.liveobjects.message.WireObjectData +import io.ably.pubsub.liveobjects.value.livecounter.InternalLiveCounter +import io.ably.pubsub.liveobjects.value.livemap.InternalLiveMap /** * The result of resolving a path segment / map entry against the objects diff --git a/liveobjects/src/main/kotlin/io/ably/lib/liveobjects/value/livecounter/DefaultLiveCounter.kt b/liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/value/livecounter/DefaultLiveCounter.kt similarity index 75% rename from liveobjects/src/main/kotlin/io/ably/lib/liveobjects/value/livecounter/DefaultLiveCounter.kt rename to liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/value/livecounter/DefaultLiveCounter.kt index 398df76cc..7dd365399 100644 --- a/liveobjects/src/main/kotlin/io/ably/lib/liveobjects/value/livecounter/DefaultLiveCounter.kt +++ b/liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/value/livecounter/DefaultLiveCounter.kt @@ -1,15 +1,15 @@ -package io.ably.lib.liveobjects.value.livecounter +package io.ably.pubsub.liveobjects.value.livecounter -import io.ably.lib.liveobjects.DefaultRealtimeObject -import io.ably.lib.liveobjects.invalidInputError -import io.ably.lib.liveobjects.message.WireCounterCreate -import io.ably.lib.liveobjects.message.WireCounterCreateWithObjectId -import io.ably.lib.liveobjects.message.WireObjectMessage -import io.ably.lib.liveobjects.message.WireObjectOperation -import io.ably.lib.liveobjects.message.WireObjectOperationAction -import io.ably.lib.liveobjects.serialization.gson -import io.ably.lib.liveobjects.value.LiveCounter -import io.ably.lib.liveobjects.value.ObjectType +import io.ably.pubsub.liveobjects.DefaultRealtimeObject +import io.ably.pubsub.liveobjects.invalidInputError +import io.ably.pubsub.liveobjects.message.WireCounterCreate +import io.ably.pubsub.liveobjects.message.WireCounterCreateWithObjectId +import io.ably.pubsub.liveobjects.message.WireObjectMessage +import io.ably.pubsub.liveobjects.message.WireObjectOperation +import io.ably.pubsub.liveobjects.message.WireObjectOperationAction +import io.ably.pubsub.liveobjects.serialization.gson +import io.ably.pubsub.liveobjects.value.LiveCounter +import io.ably.pubsub.liveobjects.value.ObjectType /** * Default implementation of the [LiveCounter] value type - an immutable holder for diff --git a/liveobjects/src/main/kotlin/io/ably/lib/liveobjects/value/livecounter/InternalLiveCounter.kt b/liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/value/livecounter/InternalLiveCounter.kt similarity index 84% rename from liveobjects/src/main/kotlin/io/ably/lib/liveobjects/value/livecounter/InternalLiveCounter.kt rename to liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/value/livecounter/InternalLiveCounter.kt index 2cd4219cf..36fed834d 100644 --- a/liveobjects/src/main/kotlin/io/ably/lib/liveobjects/value/livecounter/InternalLiveCounter.kt +++ b/liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/value/livecounter/InternalLiveCounter.kt @@ -1,15 +1,15 @@ -package io.ably.lib.liveobjects.value.livecounter - -import io.ably.lib.liveobjects.* -import io.ably.lib.liveobjects.DefaultRealtimeObject -import io.ably.lib.liveobjects.instance.DefaultInstanceSubscriptionEvent -import io.ably.lib.liveobjects.instance.InstanceListener -import io.ably.lib.liveobjects.instance.types.DefaultLiveCounterInstance -import io.ably.lib.liveobjects.invalidInputError -import io.ably.lib.liveobjects.message.* -import io.ably.lib.liveobjects.value.BaseRealtimeObject -import io.ably.lib.liveobjects.value.ObjectType -import io.ably.lib.liveobjects.value.ObjectUpdate +package io.ably.pubsub.liveobjects.value.livecounter + +import io.ably.pubsub.liveobjects.* +import io.ably.pubsub.liveobjects.DefaultRealtimeObject +import io.ably.pubsub.liveobjects.instance.DefaultInstanceSubscriptionEvent +import io.ably.pubsub.liveobjects.instance.InstanceListener +import io.ably.pubsub.liveobjects.instance.types.DefaultLiveCounterInstance +import io.ably.pubsub.liveobjects.invalidInputError +import io.ably.pubsub.liveobjects.message.* +import io.ably.pubsub.liveobjects.value.BaseRealtimeObject +import io.ably.pubsub.liveobjects.value.ObjectType +import io.ably.pubsub.liveobjects.value.ObjectUpdate import java.util.concurrent.atomic.AtomicReference /** diff --git a/liveobjects/src/main/kotlin/io/ably/lib/liveobjects/value/livecounter/LiveCounterChangeCoordinator.kt b/liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/value/livecounter/LiveCounterChangeCoordinator.kt similarity index 81% rename from liveobjects/src/main/kotlin/io/ably/lib/liveobjects/value/livecounter/LiveCounterChangeCoordinator.kt rename to liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/value/livecounter/LiveCounterChangeCoordinator.kt index 50795d299..6fe3c2a6e 100644 --- a/liveobjects/src/main/kotlin/io/ably/lib/liveobjects/value/livecounter/LiveCounterChangeCoordinator.kt +++ b/liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/value/livecounter/LiveCounterChangeCoordinator.kt @@ -1,12 +1,12 @@ -package io.ably.lib.liveobjects.value.livecounter - -import io.ably.lib.liveobjects.Subscription -import io.ably.lib.liveobjects.instance.InstanceListener -import io.ably.lib.liveobjects.instance.InstanceSubscriptionEvent -import io.ably.lib.liveobjects.onceSubscription -import io.ably.lib.liveobjects.value.ObjectUpdate -import io.ably.lib.util.EventEmitter -import io.ably.lib.util.Log +package io.ably.pubsub.liveobjects.value.livecounter + +import io.ably.pubsub.liveobjects.Subscription +import io.ably.pubsub.liveobjects.instance.InstanceListener +import io.ably.pubsub.liveobjects.instance.InstanceSubscriptionEvent +import io.ably.pubsub.liveobjects.onceSubscription +import io.ably.pubsub.liveobjects.value.ObjectUpdate +import io.ably.pubsub.util.EventEmitter +import io.ably.pubsub.util.Log internal val noOpCounterUpdate: ObjectUpdate = ObjectUpdate.NoOp diff --git a/liveobjects/src/main/kotlin/io/ably/lib/liveobjects/value/livecounter/LiveCounterManager.kt b/liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/value/livecounter/LiveCounterManager.kt similarity index 93% rename from liveobjects/src/main/kotlin/io/ably/lib/liveobjects/value/livecounter/LiveCounterManager.kt rename to liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/value/livecounter/LiveCounterManager.kt index e36c0e606..bc9479e6e 100644 --- a/liveobjects/src/main/kotlin/io/ably/lib/liveobjects/value/livecounter/LiveCounterManager.kt +++ b/liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/value/livecounter/LiveCounterManager.kt @@ -1,13 +1,13 @@ -package io.ably.lib.liveobjects.value.livecounter - -import io.ably.lib.liveobjects.message.WireCounterInc -import io.ably.lib.liveobjects.message.WireObjectMessage -import io.ably.lib.liveobjects.message.WireObjectOperation -import io.ably.lib.liveobjects.message.WireObjectOperationAction -import io.ably.lib.liveobjects.message.WireObjectState -import io.ably.lib.liveobjects.objectError -import io.ably.lib.liveobjects.value.ObjectUpdate -import io.ably.lib.util.Log +package io.ably.pubsub.liveobjects.value.livecounter + +import io.ably.pubsub.liveobjects.message.WireCounterInc +import io.ably.pubsub.liveobjects.message.WireObjectMessage +import io.ably.pubsub.liveobjects.message.WireObjectOperation +import io.ably.pubsub.liveobjects.message.WireObjectOperationAction +import io.ably.pubsub.liveobjects.message.WireObjectState +import io.ably.pubsub.liveobjects.objectError +import io.ably.pubsub.liveobjects.value.ObjectUpdate +import io.ably.pubsub.util.Log internal class LiveCounterManager(private val liveCounter: InternalLiveCounter): LiveCounterChangeCoordinator() { diff --git a/liveobjects/src/main/kotlin/io/ably/lib/liveobjects/value/livemap/DefaultLiveMap.kt b/liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/value/livemap/DefaultLiveMap.kt similarity index 82% rename from liveobjects/src/main/kotlin/io/ably/lib/liveobjects/value/livemap/DefaultLiveMap.kt rename to liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/value/livemap/DefaultLiveMap.kt index e155e0140..317cf0806 100644 --- a/liveobjects/src/main/kotlin/io/ably/lib/liveobjects/value/livemap/DefaultLiveMap.kt +++ b/liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/value/livemap/DefaultLiveMap.kt @@ -1,20 +1,20 @@ -package io.ably.lib.liveobjects.value.livemap +package io.ably.pubsub.liveobjects.value.livemap -import io.ably.lib.liveobjects.DefaultRealtimeObject -import io.ably.lib.liveobjects.invalidInputError -import io.ably.lib.liveobjects.message.WireMapCreate -import io.ably.lib.liveobjects.message.WireMapCreateWithObjectId -import io.ably.lib.liveobjects.message.WireObjectData -import io.ably.lib.liveobjects.message.WireObjectMessage -import io.ably.lib.liveobjects.message.WireObjectOperation -import io.ably.lib.liveobjects.message.WireObjectOperationAction -import io.ably.lib.liveobjects.message.WireObjectsMapEntry -import io.ably.lib.liveobjects.message.WireObjectsMapSemantics -import io.ably.lib.liveobjects.serialization.gson -import io.ably.lib.liveobjects.value.LiveMap -import io.ably.lib.liveobjects.value.LiveMapValue -import io.ably.lib.liveobjects.value.ObjectType -import io.ably.lib.liveobjects.value.livecounter.DefaultLiveCounter +import io.ably.pubsub.liveobjects.DefaultRealtimeObject +import io.ably.pubsub.liveobjects.invalidInputError +import io.ably.pubsub.liveobjects.message.WireMapCreate +import io.ably.pubsub.liveobjects.message.WireMapCreateWithObjectId +import io.ably.pubsub.liveobjects.message.WireObjectData +import io.ably.pubsub.liveobjects.message.WireObjectMessage +import io.ably.pubsub.liveobjects.message.WireObjectOperation +import io.ably.pubsub.liveobjects.message.WireObjectOperationAction +import io.ably.pubsub.liveobjects.message.WireObjectsMapEntry +import io.ably.pubsub.liveobjects.message.WireObjectsMapSemantics +import io.ably.pubsub.liveobjects.serialization.gson +import io.ably.pubsub.liveobjects.value.LiveMap +import io.ably.pubsub.liveobjects.value.LiveMapValue +import io.ably.pubsub.liveobjects.value.ObjectType +import io.ably.pubsub.liveobjects.value.livecounter.DefaultLiveCounter import java.util.Base64 /** diff --git a/liveobjects/src/main/kotlin/io/ably/lib/liveobjects/value/livemap/InternalLiveMap.kt b/liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/value/livemap/InternalLiveMap.kt similarity index 92% rename from liveobjects/src/main/kotlin/io/ably/lib/liveobjects/value/livemap/InternalLiveMap.kt rename to liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/value/livemap/InternalLiveMap.kt index 1703800db..93213e157 100644 --- a/liveobjects/src/main/kotlin/io/ably/lib/liveobjects/value/livemap/InternalLiveMap.kt +++ b/liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/value/livemap/InternalLiveMap.kt @@ -1,16 +1,16 @@ -package io.ably.lib.liveobjects.value.livemap - -import io.ably.lib.liveobjects.* -import io.ably.lib.liveobjects.ObjectsPool -import io.ably.lib.liveobjects.instance.DefaultInstanceSubscriptionEvent -import io.ably.lib.liveobjects.instance.InstanceListener -import io.ably.lib.liveobjects.instance.types.DefaultLiveMapInstance -import io.ably.lib.liveobjects.message.* -import io.ably.lib.liveobjects.value.* -import io.ably.lib.liveobjects.value.BaseRealtimeObject -import io.ably.lib.liveobjects.value.ObjectType -import io.ably.lib.liveobjects.value.ObjectUpdate -import io.ably.lib.liveobjects.value.livecounter.DefaultLiveCounter +package io.ably.pubsub.liveobjects.value.livemap + +import io.ably.pubsub.liveobjects.* +import io.ably.pubsub.liveobjects.ObjectsPool +import io.ably.pubsub.liveobjects.instance.DefaultInstanceSubscriptionEvent +import io.ably.pubsub.liveobjects.instance.InstanceListener +import io.ably.pubsub.liveobjects.instance.types.DefaultLiveMapInstance +import io.ably.pubsub.liveobjects.message.* +import io.ably.pubsub.liveobjects.value.* +import io.ably.pubsub.liveobjects.value.BaseRealtimeObject +import io.ably.pubsub.liveobjects.value.ObjectType +import io.ably.pubsub.liveobjects.value.ObjectUpdate +import io.ably.pubsub.liveobjects.value.livecounter.DefaultLiveCounter import com.google.gson.JsonObject import java.util.concurrent.ConcurrentHashMap import java.util.AbstractMap diff --git a/liveobjects/src/main/kotlin/io/ably/lib/liveobjects/value/livemap/LiveMapChangeCoordinator.kt b/liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/value/livemap/LiveMapChangeCoordinator.kt similarity index 81% rename from liveobjects/src/main/kotlin/io/ably/lib/liveobjects/value/livemap/LiveMapChangeCoordinator.kt rename to liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/value/livemap/LiveMapChangeCoordinator.kt index 5f469b91c..ec2b5f96e 100644 --- a/liveobjects/src/main/kotlin/io/ably/lib/liveobjects/value/livemap/LiveMapChangeCoordinator.kt +++ b/liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/value/livemap/LiveMapChangeCoordinator.kt @@ -1,12 +1,12 @@ -package io.ably.lib.liveobjects.value.livemap - -import io.ably.lib.liveobjects.Subscription -import io.ably.lib.liveobjects.instance.InstanceListener -import io.ably.lib.liveobjects.instance.InstanceSubscriptionEvent -import io.ably.lib.liveobjects.onceSubscription -import io.ably.lib.liveobjects.value.ObjectUpdate -import io.ably.lib.util.EventEmitter -import io.ably.lib.util.Log +package io.ably.pubsub.liveobjects.value.livemap + +import io.ably.pubsub.liveobjects.Subscription +import io.ably.pubsub.liveobjects.instance.InstanceListener +import io.ably.pubsub.liveobjects.instance.InstanceSubscriptionEvent +import io.ably.pubsub.liveobjects.onceSubscription +import io.ably.pubsub.liveobjects.value.ObjectUpdate +import io.ably.pubsub.util.EventEmitter +import io.ably.pubsub.util.Log internal val noOpMapUpdate: ObjectUpdate = ObjectUpdate.NoOp diff --git a/liveobjects/src/main/kotlin/io/ably/lib/liveobjects/value/livemap/LiveMapEntry.kt b/liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/value/livemap/LiveMapEntry.kt similarity index 84% rename from liveobjects/src/main/kotlin/io/ably/lib/liveobjects/value/livemap/LiveMapEntry.kt rename to liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/value/livemap/LiveMapEntry.kt index a8cf44ce7..5e2f68c83 100644 --- a/liveobjects/src/main/kotlin/io/ably/lib/liveobjects/value/livemap/LiveMapEntry.kt +++ b/liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/value/livemap/LiveMapEntry.kt @@ -1,12 +1,12 @@ -package io.ably.lib.liveobjects.value.livemap +package io.ably.pubsub.liveobjects.value.livemap -import io.ably.lib.liveobjects.ObjectsPool -import io.ably.lib.liveobjects.message.WireObjectData -import io.ably.lib.liveobjects.message.isInvalid -import io.ably.lib.liveobjects.value.ObjectType -import io.ably.lib.liveobjects.value.ResolvedValue -import io.ably.lib.liveobjects.value.livecounter.InternalLiveCounter -import io.ably.lib.util.Clock +import io.ably.pubsub.liveobjects.ObjectsPool +import io.ably.pubsub.liveobjects.message.WireObjectData +import io.ably.pubsub.liveobjects.message.isInvalid +import io.ably.pubsub.liveobjects.value.ObjectType +import io.ably.pubsub.liveobjects.value.ResolvedValue +import io.ably.pubsub.liveobjects.value.livecounter.InternalLiveCounter +import io.ably.pubsub.util.Clock /** * @spec RTLM3 - Map data structure storing entries diff --git a/liveobjects/src/main/kotlin/io/ably/lib/liveobjects/value/livemap/LiveMapManager.kt b/liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/value/livemap/LiveMapManager.kt similarity index 98% rename from liveobjects/src/main/kotlin/io/ably/lib/liveobjects/value/livemap/LiveMapManager.kt rename to liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/value/livemap/LiveMapManager.kt index 72d915975..2cb43f75e 100644 --- a/liveobjects/src/main/kotlin/io/ably/lib/liveobjects/value/livemap/LiveMapManager.kt +++ b/liveobjects/src/main/kotlin/io/ably/pubsub/liveobjects/value/livemap/LiveMapManager.kt @@ -1,9 +1,9 @@ -package io.ably.lib.liveobjects.value.livemap +package io.ably.pubsub.liveobjects.value.livemap -import io.ably.lib.liveobjects.message.* -import io.ably.lib.liveobjects.objectError -import io.ably.lib.liveobjects.value.ObjectUpdate -import io.ably.lib.util.Log +import io.ably.pubsub.liveobjects.message.* +import io.ably.pubsub.liveobjects.objectError +import io.ably.pubsub.liveobjects.value.ObjectUpdate +import io.ably.pubsub.util.Log internal class LiveMapManager(private val liveMap: InternalLiveMap): LiveMapChangeCoordinator() { diff --git a/liveobjects/src/test/kotlin/io/ably/lib/liveobjects/TestUtils.kt b/liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/TestUtils.kt similarity index 98% rename from liveobjects/src/test/kotlin/io/ably/lib/liveobjects/TestUtils.kt rename to liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/TestUtils.kt index 65c712463..038a94fb9 100644 --- a/liveobjects/src/test/kotlin/io/ably/lib/liveobjects/TestUtils.kt +++ b/liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/TestUtils.kt @@ -1,4 +1,4 @@ -package io.ably.lib.liveobjects +package io.ably.pubsub.liveobjects import java.lang.reflect.Field import kotlinx.coroutines.Dispatchers diff --git a/liveobjects/src/test/kotlin/io/ably/lib/liveobjects/integration/DefaultRealtimeObjectTest.kt b/liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/integration/DefaultRealtimeObjectTest.kt similarity index 87% rename from liveobjects/src/test/kotlin/io/ably/lib/liveobjects/integration/DefaultRealtimeObjectTest.kt rename to liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/integration/DefaultRealtimeObjectTest.kt index 7fc44f60a..db2842cbb 100644 --- a/liveobjects/src/test/kotlin/io/ably/lib/liveobjects/integration/DefaultRealtimeObjectTest.kt +++ b/liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/integration/DefaultRealtimeObjectTest.kt @@ -1,8 +1,8 @@ -package io.ably.lib.liveobjects.integration +package io.ably.pubsub.liveobjects.integration -import io.ably.lib.liveobjects.assertWaiter -import io.ably.lib.liveobjects.integration.setup.IntegrationTest -import io.ably.lib.realtime.ChannelState +import io.ably.pubsub.liveobjects.assertWaiter +import io.ably.pubsub.liveobjects.integration.setup.IntegrationTest +import io.ably.pubsub.realtime.ChannelState import kotlinx.coroutines.test.runTest import org.junit.Test import kotlin.test.assertEquals diff --git a/liveobjects/src/test/kotlin/io/ably/lib/liveobjects/integration/helpers/RestObjects.kt b/liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/integration/helpers/HttpObjects.kt similarity index 76% rename from liveobjects/src/test/kotlin/io/ably/lib/liveobjects/integration/helpers/RestObjects.kt rename to liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/integration/helpers/HttpObjects.kt index 62ef8d7d5..4b043179d 100644 --- a/liveobjects/src/test/kotlin/io/ably/lib/liveobjects/integration/helpers/RestObjects.kt +++ b/liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/integration/helpers/HttpObjects.kt @@ -1,25 +1,26 @@ -package io.ably.lib.liveobjects.integration.helpers +package io.ably.pubsub.liveobjects.integration.helpers import com.google.gson.JsonObject -import io.ably.lib.liveobjects.message.WireObjectData -import io.ably.lib.rest.AblyRest -import io.ably.lib.http.HttpUtils -import io.ably.lib.liveobjects.integration.helpers.fixtures.DataFixtures -import io.ably.lib.types.ClientOptions +import io.ably.pubsub.liveobjects.message.WireObjectData +import io.ably.pubsub.http.HttpClientFactory +import io.ably.pubsub.http.PubSubHttpClient +import io.ably.pubsub.http.HttpUtils +import io.ably.pubsub.liveobjects.integration.helpers.fixtures.DataFixtures +import io.ably.pubsub.types.ClientOptions /** * Helper class to create pre-determined objects and modify them on channels using rest api. */ -internal class RestObjects(options: ClientOptions) { +internal class HttpObjects(options: ClientOptions) { - private val ablyRest: AblyRest = AblyRest(options) + private val pubSubHttpClient: PubSubHttpClient = HttpClientFactory.create(options) /** * Creates a new map object on the channel with optional initial data. * @return The object ID of the created map */ internal fun createMap(channelName: String, data: Map? = null): String { - val mapCreateOp = PayloadBuilder.mapCreateRestOp(data = data) + val mapCreateOp = PayloadBuilder.mapCreateHttpOp(data = data) return operationRequest(channelName, mapCreateOp).objectId ?: throw Exception("Failed to create map: no objectId returned") } @@ -28,7 +29,7 @@ internal class RestObjects(options: ClientOptions) { * Sets a value (primitives, JsonObject, JsonArray, etc.) at the specified key in an existing map. */ internal fun setMapValue(channelName: String, mapObjectId: String, key: String, data: WireObjectData) { - val mapCreateOp = PayloadBuilder.mapSetRestOp(mapObjectId, key, data) + val mapCreateOp = PayloadBuilder.mapSetHttpOp(mapObjectId, key, data) operationRequest(channelName, mapCreateOp) } @@ -36,7 +37,7 @@ internal class RestObjects(options: ClientOptions) { * Sets an object reference at the specified key in an existing map. */ internal fun setMapRef(channelName: String, mapObjectId: String, key: String, refMapObjectId: String) { - val mapCreateOp = PayloadBuilder.mapSetRestOp(mapObjectId, key, DataFixtures.mapRef(refMapObjectId)) + val mapCreateOp = PayloadBuilder.mapSetHttpOp(mapObjectId, key, DataFixtures.mapRef(refMapObjectId)) operationRequest(channelName, mapCreateOp) } @@ -44,7 +45,7 @@ internal class RestObjects(options: ClientOptions) { * Removes a key-value pair from an existing map. */ internal fun removeMapValue(channelName: String, mapObjectId: String, key: String) { - val mapRemoveOp = PayloadBuilder.mapRemoveRestOp(mapObjectId, key) + val mapRemoveOp = PayloadBuilder.mapRemoveHttpOp(mapObjectId, key) operationRequest(channelName, mapRemoveOp) } @@ -53,7 +54,7 @@ internal class RestObjects(options: ClientOptions) { * @return The object ID of the created counter */ internal fun createCounter(channelName: String, initialValue: Double? = null): String { - val counterCreateOp = PayloadBuilder.counterCreateRestOp(number = initialValue) + val counterCreateOp = PayloadBuilder.counterCreateHttpOp(number = initialValue) return operationRequest(channelName, counterCreateOp).objectId ?: throw Exception("Failed to create counter: no objectId returned") } @@ -62,7 +63,7 @@ internal class RestObjects(options: ClientOptions) { * Increments an existing counter by the specified amount. */ internal fun incrementCounter(channelName: String, counterObjectId: String, incrementBy: Double) { - val counterIncrementOp = PayloadBuilder.counterIncRestOp(counterObjectId, incrementBy) + val counterIncrementOp = PayloadBuilder.counterIncHttpOp(counterObjectId, incrementBy) operationRequest(channelName, counterIncrementOp) } @@ -70,7 +71,7 @@ internal class RestObjects(options: ClientOptions) { * Decrements an existing counter by the specified amount. */ internal fun decrementCounter(channelName: String, counterObjectId: String, decrementBy: Double) { - val counterDecrementOp = PayloadBuilder.counterIncRestOp(counterObjectId, -decrementBy) + val counterDecrementOp = PayloadBuilder.counterIncHttpOp(counterObjectId, -decrementBy) operationRequest(channelName, counterDecrementOp) } @@ -81,9 +82,9 @@ internal class RestObjects(options: ClientOptions) { private fun operationRequest(channelName: String, opBody: JsonObject): OperationResult { try { val path = "/channels/$channelName/objects" - val requestBody = HttpUtils.requestBodyFromGson(opBody, ablyRest.options.useBinaryProtocol) + val requestBody = HttpUtils.requestBodyFromGson(opBody, pubSubHttpClient.options.useBinaryProtocol) - val response = ablyRest.request("POST", path, null, requestBody, null) + val response = pubSubHttpClient.request("POST", path, null, requestBody, null) if (!response.success) { throw Exception("REST operation failed: HTTP ${response.statusCode} - ${response.errorMessage}") diff --git a/liveobjects/src/test/kotlin/io/ably/lib/liveobjects/integration/helpers/PayloadBuilder.kt b/liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/integration/helpers/PayloadBuilder.kt similarity index 85% rename from liveobjects/src/test/kotlin/io/ably/lib/liveobjects/integration/helpers/PayloadBuilder.kt rename to liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/integration/helpers/PayloadBuilder.kt index 2f025059c..daf987734 100644 --- a/liveobjects/src/test/kotlin/io/ably/lib/liveobjects/integration/helpers/PayloadBuilder.kt +++ b/liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/integration/helpers/PayloadBuilder.kt @@ -1,10 +1,10 @@ -package io.ably.lib.liveobjects.integration.helpers +package io.ably.pubsub.liveobjects.integration.helpers import com.google.gson.JsonObject -import io.ably.lib.liveobjects.generateNonce -import io.ably.lib.liveobjects.message.WireObjectData -import io.ably.lib.liveobjects.message.WireObjectOperationAction -import io.ably.lib.liveobjects.serialization.gson +import io.ably.pubsub.liveobjects.generateNonce +import io.ably.pubsub.liveobjects.message.WireObjectData +import io.ably.pubsub.liveobjects.message.WireObjectOperationAction +import io.ably.pubsub.liveobjects.serialization.gson internal object PayloadBuilder { /** @@ -26,7 +26,7 @@ internal object PayloadBuilder { * @param data Optional initial data for the map * @param nonce Optional nonce for deterministic object ID generation */ - internal fun mapCreateRestOp( + internal fun mapCreateHttpOp( objectId: String? = null, data: Map? = null, nonce: String? = null, @@ -51,7 +51,7 @@ internal object PayloadBuilder { /** * Creates a MAP_SET operation payload for REST API. */ - internal fun mapSetRestOp(objectId: String, key: String, value: WireObjectData): JsonObject { + internal fun mapSetHttpOp(objectId: String, key: String, value: WireObjectData): JsonObject { val opBody = JsonObject().apply { addProperty("operation", ACTION_STRINGS[WireObjectOperationAction.MapSet]) addProperty("objectId", objectId) @@ -69,7 +69,7 @@ internal object PayloadBuilder { /** * Creates a MAP_REMOVE operation payload for REST API. */ - internal fun mapRemoveRestOp(objectId: String, key: String): JsonObject { + internal fun mapRemoveHttpOp(objectId: String, key: String): JsonObject { val opBody = JsonObject().apply { addProperty("operation", ACTION_STRINGS[WireObjectOperationAction.MapRemove]) addProperty("objectId", objectId) @@ -90,7 +90,7 @@ internal object PayloadBuilder { * @param nonce Optional nonce for deterministic object ID generation * @param number Optional initial counter value */ - internal fun counterCreateRestOp( + internal fun counterCreateHttpOp( objectId: String? = null, number: Double? = null, nonce: String? = null, @@ -117,7 +117,7 @@ internal object PayloadBuilder { /** * Creates a COUNTER_INC operation payload for REST API. */ - internal fun counterIncRestOp(objectId: String, number: Double): JsonObject { + internal fun counterIncHttpOp(objectId: String, number: Double): JsonObject { val opBody = JsonObject().apply { addProperty("operation", ACTION_STRINGS[WireObjectOperationAction.CounterInc]) addProperty("objectId", objectId) diff --git a/liveobjects/src/test/kotlin/io/ably/lib/liveobjects/integration/helpers/fixtures/CounterFixtures.kt b/liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/integration/helpers/fixtures/CounterFixtures.kt similarity index 93% rename from liveobjects/src/test/kotlin/io/ably/lib/liveobjects/integration/helpers/fixtures/CounterFixtures.kt rename to liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/integration/helpers/fixtures/CounterFixtures.kt index 86f454d41..4c6e23f18 100644 --- a/liveobjects/src/test/kotlin/io/ably/lib/liveobjects/integration/helpers/fixtures/CounterFixtures.kt +++ b/liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/integration/helpers/fixtures/CounterFixtures.kt @@ -1,6 +1,6 @@ -package io.ably.lib.liveobjects.integration.helpers.fixtures +package io.ably.pubsub.liveobjects.integration.helpers.fixtures -import io.ably.lib.liveobjects.integration.helpers.RestObjects +import io.ably.pubsub.liveobjects.integration.helpers.HttpObjects /** * Creates a comprehensive test fixture object tree focused on user-context counters. @@ -29,7 +29,7 @@ import io.ably.lib.liveobjects.integration.helpers.RestObjects * @param channelName The channel where the counter object tree will be created * @return The object ID of the root test map containing all counter references */ -internal fun RestObjects.createUserMapWithCountersObject(channelName: String): String { +internal fun HttpObjects.createUserMapWithCountersObject(channelName: String): String { // Create the main test map first val testMapObjectId = createMap(channelName) @@ -75,7 +75,7 @@ internal fun RestObjects.createUserMapWithCountersObject(channelName: String): S * @param channelName The channel where the user engagement matrix map will be created * @return The object ID of the created user engagement matrix map */ -internal fun RestObjects.createUserEngagementMatrixMap(channelName: String): String { +internal fun HttpObjects.createUserEngagementMatrixMap(channelName: String): String { return createMap( channelName, data = mapOf( diff --git a/liveobjects/src/test/kotlin/io/ably/lib/liveobjects/integration/helpers/fixtures/DataFixtures.kt b/liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/integration/helpers/fixtures/DataFixtures.kt similarity index 96% rename from liveobjects/src/test/kotlin/io/ably/lib/liveobjects/integration/helpers/fixtures/DataFixtures.kt rename to liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/integration/helpers/fixtures/DataFixtures.kt index 57227dc7e..34b659e01 100644 --- a/liveobjects/src/test/kotlin/io/ably/lib/liveobjects/integration/helpers/fixtures/DataFixtures.kt +++ b/liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/integration/helpers/fixtures/DataFixtures.kt @@ -1,8 +1,8 @@ -package io.ably.lib.liveobjects.integration.helpers.fixtures +package io.ably.pubsub.liveobjects.integration.helpers.fixtures import com.google.gson.JsonArray import com.google.gson.JsonObject -import io.ably.lib.liveobjects.message.WireObjectData +import io.ably.pubsub.liveobjects.message.WireObjectData import java.util.Base64 internal object DataFixtures { diff --git a/liveobjects/src/test/kotlin/io/ably/lib/liveobjects/integration/helpers/fixtures/MapFixtures.kt b/liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/integration/helpers/fixtures/MapFixtures.kt similarity index 94% rename from liveobjects/src/test/kotlin/io/ably/lib/liveobjects/integration/helpers/fixtures/MapFixtures.kt rename to liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/integration/helpers/fixtures/MapFixtures.kt index 2d92233e2..44f3b29cf 100644 --- a/liveobjects/src/test/kotlin/io/ably/lib/liveobjects/integration/helpers/fixtures/MapFixtures.kt +++ b/liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/integration/helpers/fixtures/MapFixtures.kt @@ -1,7 +1,7 @@ -package io.ably.lib.liveobjects.integration.helpers.fixtures +package io.ably.pubsub.liveobjects.integration.helpers.fixtures -import io.ably.lib.liveobjects.message.WireObjectData -import io.ably.lib.liveobjects.integration.helpers.RestObjects +import io.ably.pubsub.liveobjects.message.WireObjectData +import io.ably.pubsub.liveobjects.integration.helpers.HttpObjects /** * Initializes a comprehensive test fixture object tree on the specified channel. @@ -38,7 +38,7 @@ import io.ably.lib.liveobjects.integration.helpers.RestObjects * * @param channelName The channel where the object tree will be created */ -internal fun RestObjects.initializeRootMap(channelName: String) { +internal fun HttpObjects.initializeRootMap(channelName: String) { // Create counters val emptyCounterObjectId = createCounter(channelName) setMapRef(channelName, "root", "emptyCounter", emptyCounterObjectId) @@ -102,7 +102,7 @@ internal fun RestObjects.initializeRootMap(channelName: String) { * * @param channelName The channel where the test object tree will be created */ -internal fun RestObjects.createUserMapObject(channelName: String): String { +internal fun HttpObjects.createUserMapObject(channelName: String): String { // Create the main test map first val testMapObjectId = createMap(channelName) @@ -170,7 +170,7 @@ internal fun RestObjects.createUserMapObject(channelName: String): String { * @param channelName The channel where the user profile map will be created * @return The object ID of the created user profile map */ -internal fun RestObjects.createUserProfileMapObject(channelName: String): String { +internal fun HttpObjects.createUserProfileMapObject(channelName: String): String { return createMap( channelName, data = mapOf( diff --git a/liveobjects/src/test/kotlin/io/ably/lib/liveobjects/integration/setup/IntegrationTest.kt b/liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/integration/setup/IntegrationTest.kt similarity index 77% rename from liveobjects/src/test/kotlin/io/ably/lib/liveobjects/integration/setup/IntegrationTest.kt rename to liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/integration/setup/IntegrationTest.kt index 7fcfa8345..0093fbb09 100644 --- a/liveobjects/src/test/kotlin/io/ably/lib/liveobjects/integration/setup/IntegrationTest.kt +++ b/liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/integration/setup/IntegrationTest.kt @@ -1,10 +1,10 @@ -package io.ably.lib.liveobjects.integration.setup +package io.ably.pubsub.liveobjects.integration.setup -import io.ably.lib.liveobjects.integration.helpers.RestObjects -import io.ably.lib.realtime.AblyRealtime -import io.ably.lib.realtime.Channel -import io.ably.lib.types.ChannelMode -import io.ably.lib.types.ChannelOptions +import io.ably.pubsub.liveobjects.integration.helpers.HttpObjects +import io.ably.pubsub.realtime.PubSubRealtimeClient +import io.ably.pubsub.realtime.Channel +import io.ably.pubsub.types.ChannelMode +import io.ably.pubsub.types.ChannelOptions import kotlinx.coroutines.runBlocking import org.junit.After import org.junit.AfterClass @@ -24,7 +24,7 @@ abstract class IntegrationTest { @Rule val timeout: Timeout = Timeout.seconds(15) - private val realtimeClients = mutableMapOf() + private val realtimeClients = mutableMapOf() /** * Retrieves a realtime channel for the specified channel name and client ID @@ -58,19 +58,19 @@ abstract class IntegrationTest { @After fun afterEach() { - for (ablyRealtime in realtimeClients.values) { - for ((channelName, channel) in ablyRealtime.channels.entrySet()) { + for (realtimeClient in realtimeClients.values) { + for ((channelName, channel) in realtimeClient.channels.entrySet()) { channel.off() - ablyRealtime.channels.release(channelName) + realtimeClient.channels.release(channelName) } - ablyRealtime.close() + realtimeClient.close() } realtimeClients.clear() } companion object { private lateinit var sandbox: Sandbox - internal lateinit var restObjects: RestObjects + internal lateinit var httpObjects: HttpObjects @JvmStatic @Parameterized.Parameters(name = "{0}") @@ -84,7 +84,7 @@ abstract class IntegrationTest { fun setUpBeforeClass() { runBlocking { sandbox = Sandbox.createInstance() - restObjects = sandbox.createRestObjects() + httpObjects = sandbox.createHttpObjects() } } diff --git a/liveobjects/src/test/kotlin/io/ably/lib/liveobjects/integration/setup/Sandbox.kt b/liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/integration/setup/Sandbox.kt similarity index 67% rename from liveobjects/src/test/kotlin/io/ably/lib/liveobjects/integration/setup/Sandbox.kt rename to liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/integration/setup/Sandbox.kt index 86dc9498d..edbddc48d 100644 --- a/liveobjects/src/test/kotlin/io/ably/lib/liveobjects/integration/setup/Sandbox.kt +++ b/liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/integration/setup/Sandbox.kt @@ -1,12 +1,13 @@ -package io.ably.lib.liveobjects.integration.setup +package io.ably.pubsub.liveobjects.integration.setup -import io.ably.lib.liveobjects.ablyException -import io.ably.lib.liveobjects.integration.helpers.RestObjects -import io.ably.lib.realtime.AblyRealtime -import io.ably.lib.realtime.ConnectionEvent -import io.ably.lib.realtime.ConnectionState -import io.ably.lib.types.ClientOptions -import io.ably.lib.uts.infra.integration.SandboxApp +import io.ably.pubsub.liveobjects.ablyException +import io.ably.pubsub.liveobjects.integration.helpers.HttpObjects +import io.ably.pubsub.realtime.PubSubRealtimeClient +import io.ably.pubsub.realtime.RealtimeClientFactory +import io.ably.pubsub.realtime.ConnectionEvent +import io.ably.pubsub.realtime.ConnectionState +import io.ably.pubsub.types.ClientOptions +import io.ably.pubsub.uts.infra.integration.SandboxApp import kotlinx.coroutines.CompletableDeferred /** @@ -28,25 +29,25 @@ class Sandbox private constructor(private val app: SandboxApp, val appId: String internal suspend fun delete() = app.delete() } -internal fun Sandbox.createRealtimeClient(options: ClientOptions.() -> Unit): AblyRealtime { +internal fun Sandbox.createRealtimeClient(options: ClientOptions.() -> Unit): PubSubRealtimeClient { val clientOptions = ClientOptions().apply { apply(options) key = apiKey - environment = "sandbox" + endpoint = SandboxApp.sandboxEndpoint } - return AblyRealtime(clientOptions) + return RealtimeClientFactory.create(clientOptions) } -internal fun Sandbox.createRestObjects(): RestObjects { +internal fun Sandbox.createHttpObjects(): HttpObjects { val options = ClientOptions().apply { key = apiKey - environment = "sandbox" + endpoint = SandboxApp.sandboxEndpoint useBinaryProtocol = false } - return RestObjects(options) + return HttpObjects(options) } -internal suspend fun AblyRealtime.ensureConnected() { +internal suspend fun PubSubRealtimeClient.ensureConnected() { if (this.connection.state == ConnectionState.connected) { return } diff --git a/liveobjects/src/test/kotlin/io/ably/lib/liveobjects/unit/DefaultRealtimeObjectAsyncTest.kt b/liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/unit/DefaultRealtimeObjectAsyncTest.kt similarity index 93% rename from liveobjects/src/test/kotlin/io/ably/lib/liveobjects/unit/DefaultRealtimeObjectAsyncTest.kt rename to liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/unit/DefaultRealtimeObjectAsyncTest.kt index 8c42bada4..e479f17de 100644 --- a/liveobjects/src/test/kotlin/io/ably/lib/liveobjects/unit/DefaultRealtimeObjectAsyncTest.kt +++ b/liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/unit/DefaultRealtimeObjectAsyncTest.kt @@ -1,8 +1,8 @@ -package io.ably.lib.liveobjects.unit +package io.ably.pubsub.liveobjects.unit -import io.ably.lib.liveobjects.DefaultRealtimeObject -import io.ably.lib.types.AblyException -import io.ably.lib.types.ErrorInfo +import io.ably.pubsub.liveobjects.DefaultRealtimeObject +import io.ably.pubsub.types.AblyException +import io.ably.pubsub.types.ErrorInfo import io.mockk.unmockkAll import org.junit.After import org.junit.Assert.assertEquals diff --git a/liveobjects/src/test/kotlin/io/ably/lib/liveobjects/unit/DefaultRealtimeObjectChannelStateTest.kt b/liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/unit/DefaultRealtimeObjectChannelStateTest.kt similarity index 88% rename from liveobjects/src/test/kotlin/io/ably/lib/liveobjects/unit/DefaultRealtimeObjectChannelStateTest.kt rename to liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/unit/DefaultRealtimeObjectChannelStateTest.kt index 19fa6c3ae..c9abea12a 100644 --- a/liveobjects/src/test/kotlin/io/ably/lib/liveobjects/unit/DefaultRealtimeObjectChannelStateTest.kt +++ b/liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/unit/DefaultRealtimeObjectChannelStateTest.kt @@ -1,12 +1,12 @@ -package io.ably.lib.liveobjects.unit +package io.ably.pubsub.liveobjects.unit -import io.ably.lib.liveobjects.DefaultRealtimeObject -import io.ably.lib.liveobjects.ROOT_OBJECT_ID -import io.ably.lib.liveobjects.message.WireObjectData -import io.ably.lib.liveobjects.value.livecounter.InternalLiveCounter -import io.ably.lib.liveobjects.value.livemap.InternalLiveMap -import io.ably.lib.liveobjects.value.livemap.LiveMapEntry -import io.ably.lib.realtime.ChannelState +import io.ably.pubsub.liveobjects.DefaultRealtimeObject +import io.ably.pubsub.liveobjects.ROOT_OBJECT_ID +import io.ably.pubsub.liveobjects.message.WireObjectData +import io.ably.pubsub.liveobjects.value.livecounter.InternalLiveCounter +import io.ably.pubsub.liveobjects.value.livemap.InternalLiveMap +import io.ably.pubsub.liveobjects.value.livemap.LiveMapEntry +import io.ably.pubsub.realtime.ChannelState import io.mockk.unmockkAll import kotlinx.coroutines.future.await import kotlinx.coroutines.test.runTest diff --git a/liveobjects/src/test/kotlin/io/ably/lib/liveobjects/unit/HelpersTest.kt b/liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/unit/HelpersTest.kt similarity index 97% rename from liveobjects/src/test/kotlin/io/ably/lib/liveobjects/unit/HelpersTest.kt rename to liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/unit/HelpersTest.kt index 0c20d27f5..2f220b1d9 100644 --- a/liveobjects/src/test/kotlin/io/ably/lib/liveobjects/unit/HelpersTest.kt +++ b/liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/unit/HelpersTest.kt @@ -1,16 +1,16 @@ -package io.ably.lib.liveobjects.unit - -import io.ably.lib.liveobjects.* -import io.ably.lib.liveobjects.adapter.AblyClientAdapter -import io.ably.lib.liveobjects.clientError -import io.ably.lib.liveobjects.connectionManager -import io.ably.lib.liveobjects.sendAsync -import io.ably.lib.realtime.Channel -import io.ably.lib.realtime.ChannelState -import io.ably.lib.realtime.CompletionListener -import io.ably.lib.realtime.ConnectionEvent -import io.ably.lib.realtime.ConnectionStateListener -import io.ably.lib.types.* +package io.ably.pubsub.liveobjects.unit + +import io.ably.pubsub.liveobjects.* +import io.ably.pubsub.liveobjects.adapter.AblyClientAdapter +import io.ably.pubsub.liveobjects.clientError +import io.ably.pubsub.liveobjects.connectionManager +import io.ably.pubsub.liveobjects.sendAsync +import io.ably.pubsub.realtime.Channel +import io.ably.pubsub.realtime.ChannelState +import io.ably.pubsub.realtime.CompletionListener +import io.ably.pubsub.realtime.ConnectionEvent +import io.ably.pubsub.realtime.ConnectionStateListener +import io.ably.pubsub.types.* import io.mockk.* import kotlinx.coroutines.test.runTest import org.junit.Assert.* diff --git a/liveobjects/src/test/kotlin/io/ably/lib/liveobjects/unit/LiveObjectTombstoneTest.kt b/liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/unit/LiveObjectTombstoneTest.kt similarity index 76% rename from liveobjects/src/test/kotlin/io/ably/lib/liveobjects/unit/LiveObjectTombstoneTest.kt rename to liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/unit/LiveObjectTombstoneTest.kt index 364eacbad..060b0356a 100644 --- a/liveobjects/src/test/kotlin/io/ably/lib/liveobjects/unit/LiveObjectTombstoneTest.kt +++ b/liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/unit/LiveObjectTombstoneTest.kt @@ -1,18 +1,18 @@ -package io.ably.lib.liveobjects.unit +package io.ably.pubsub.liveobjects.unit -import io.ably.lib.liveobjects.DefaultRealtimeObject -import io.ably.lib.liveobjects.ObjectsOperationSource -import io.ably.lib.liveobjects.message.WireObjectData -import io.ably.lib.liveobjects.message.WireObjectDelete -import io.ably.lib.liveobjects.message.WireObjectMessage -import io.ably.lib.liveobjects.message.WireObjectOperation -import io.ably.lib.liveobjects.message.WireObjectOperationAction -import io.ably.lib.liveobjects.message.WireObjectState -import io.ably.lib.liveobjects.message.WireObjectsMap -import io.ably.lib.liveobjects.message.WireObjectsMapSemantics -import io.ably.lib.liveobjects.value.ObjectUpdate -import io.ably.lib.liveobjects.value.livemap.InternalLiveMap -import io.ably.lib.liveobjects.value.livemap.LiveMapEntry +import io.ably.pubsub.liveobjects.DefaultRealtimeObject +import io.ably.pubsub.liveobjects.ObjectsOperationSource +import io.ably.pubsub.liveobjects.message.WireObjectData +import io.ably.pubsub.liveobjects.message.WireObjectDelete +import io.ably.pubsub.liveobjects.message.WireObjectMessage +import io.ably.pubsub.liveobjects.message.WireObjectOperation +import io.ably.pubsub.liveobjects.message.WireObjectOperationAction +import io.ably.pubsub.liveobjects.message.WireObjectState +import io.ably.pubsub.liveobjects.message.WireObjectsMap +import io.ably.pubsub.liveobjects.message.WireObjectsMapSemantics +import io.ably.pubsub.liveobjects.value.ObjectUpdate +import io.ably.pubsub.liveobjects.value.livemap.InternalLiveMap +import io.ably.pubsub.liveobjects.value.livemap.LiveMapEntry import io.mockk.unmockkAll import org.junit.After import org.junit.Assert.assertEquals diff --git a/liveobjects/src/test/kotlin/io/ably/lib/liveobjects/unit/ObjectMessageSerializationTest.kt b/liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/unit/ObjectMessageSerializationTest.kt similarity index 90% rename from liveobjects/src/test/kotlin/io/ably/lib/liveobjects/unit/ObjectMessageSerializationTest.kt rename to liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/unit/ObjectMessageSerializationTest.kt index 3a94be91d..861774bb1 100644 --- a/liveobjects/src/test/kotlin/io/ably/lib/liveobjects/unit/ObjectMessageSerializationTest.kt +++ b/liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/unit/ObjectMessageSerializationTest.kt @@ -1,20 +1,20 @@ -package io.ably.lib.liveobjects.unit +package io.ably.pubsub.liveobjects.unit import com.google.gson.Gson import com.google.gson.GsonBuilder import com.google.gson.JsonElement import com.google.gson.JsonNull -import io.ably.lib.liveobjects.unit.fixtures.dummyObjectMessageWithBinaryData -import io.ably.lib.liveobjects.unit.fixtures.dummyObjectMessageWithBooleanData -import io.ably.lib.liveobjects.unit.fixtures.dummyObjectMessageWithJsonArrayData -import io.ably.lib.liveobjects.unit.fixtures.dummyObjectMessageWithJsonObjectData -import io.ably.lib.liveobjects.unit.fixtures.dummyObjectMessageWithNumberData -import io.ably.lib.liveobjects.unit.fixtures.dummyObjectMessageWithStringData -import io.ably.lib.liveobjects.message.WireObjectMessage -import io.ably.lib.types.ProtocolMessage -import io.ably.lib.types.ProtocolMessage.ActionSerializer -import io.ably.lib.types.ProtocolSerializer -import io.ably.lib.util.Serialisation +import io.ably.pubsub.liveobjects.unit.fixtures.dummyObjectMessageWithBinaryData +import io.ably.pubsub.liveobjects.unit.fixtures.dummyObjectMessageWithBooleanData +import io.ably.pubsub.liveobjects.unit.fixtures.dummyObjectMessageWithJsonArrayData +import io.ably.pubsub.liveobjects.unit.fixtures.dummyObjectMessageWithJsonObjectData +import io.ably.pubsub.liveobjects.unit.fixtures.dummyObjectMessageWithNumberData +import io.ably.pubsub.liveobjects.unit.fixtures.dummyObjectMessageWithStringData +import io.ably.pubsub.liveobjects.message.WireObjectMessage +import io.ably.pubsub.types.ProtocolMessage +import io.ably.pubsub.types.ProtocolMessage.ActionSerializer +import io.ably.pubsub.types.ProtocolSerializer +import io.ably.pubsub.util.Serialisation import kotlinx.coroutines.test.runTest import org.junit.Assert.assertEquals import org.junit.Test diff --git a/liveobjects/src/test/kotlin/io/ably/lib/liveobjects/unit/ObjectMessageSizeTest.kt b/liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/unit/ObjectMessageSizeTest.kt similarity index 87% rename from liveobjects/src/test/kotlin/io/ably/lib/liveobjects/unit/ObjectMessageSizeTest.kt rename to liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/unit/ObjectMessageSizeTest.kt index 52725680d..2e8cea1ec 100644 --- a/liveobjects/src/test/kotlin/io/ably/lib/liveobjects/unit/ObjectMessageSizeTest.kt +++ b/liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/unit/ObjectMessageSizeTest.kt @@ -1,26 +1,26 @@ -package io.ably.lib.liveobjects.unit +package io.ably.pubsub.liveobjects.unit import com.google.gson.JsonObject -import io.ably.lib.liveobjects.connectionManager -import io.ably.lib.liveobjects.ensureMessageSizeWithinLimit -import io.ably.lib.liveobjects.message.WireCounterCreate -import io.ably.lib.liveobjects.message.WireCounterCreateWithObjectId -import io.ably.lib.liveobjects.message.WireCounterInc -import io.ably.lib.liveobjects.message.WireMapCreate -import io.ably.lib.liveobjects.message.WireMapCreateWithObjectId -import io.ably.lib.liveobjects.message.WireMapSet -import io.ably.lib.liveobjects.message.WireObjectData -import io.ably.lib.liveobjects.message.WireObjectMessage -import io.ably.lib.liveobjects.message.WireObjectOperation -import io.ably.lib.liveobjects.message.WireObjectOperationAction -import io.ably.lib.liveobjects.message.WireObjectState -import io.ably.lib.liveobjects.message.WireObjectsCounter -import io.ably.lib.liveobjects.message.WireObjectsMap -import io.ably.lib.liveobjects.message.WireObjectsMapEntry -import io.ably.lib.liveobjects.message.WireObjectsMapSemantics -import io.ably.lib.liveobjects.message.size -import io.ably.lib.transport.Defaults -import io.ably.lib.types.AblyException +import io.ably.pubsub.liveobjects.connectionManager +import io.ably.pubsub.liveobjects.ensureMessageSizeWithinLimit +import io.ably.pubsub.liveobjects.message.WireCounterCreate +import io.ably.pubsub.liveobjects.message.WireCounterCreateWithObjectId +import io.ably.pubsub.liveobjects.message.WireCounterInc +import io.ably.pubsub.liveobjects.message.WireMapCreate +import io.ably.pubsub.liveobjects.message.WireMapCreateWithObjectId +import io.ably.pubsub.liveobjects.message.WireMapSet +import io.ably.pubsub.liveobjects.message.WireObjectData +import io.ably.pubsub.liveobjects.message.WireObjectMessage +import io.ably.pubsub.liveobjects.message.WireObjectOperation +import io.ably.pubsub.liveobjects.message.WireObjectOperationAction +import io.ably.pubsub.liveobjects.message.WireObjectState +import io.ably.pubsub.liveobjects.message.WireObjectsCounter +import io.ably.pubsub.liveobjects.message.WireObjectsMap +import io.ably.pubsub.liveobjects.message.WireObjectsMapEntry +import io.ably.pubsub.liveobjects.message.WireObjectsMapSemantics +import io.ably.pubsub.liveobjects.message.size +import io.ably.pubsub.transport.Defaults +import io.ably.pubsub.types.AblyException import kotlinx.coroutines.test.runTest import org.junit.Test import kotlin.test.assertEquals diff --git a/liveobjects/src/test/kotlin/io/ably/lib/liveobjects/unit/PathSegmentsTest.kt b/liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/unit/PathSegmentsTest.kt similarity index 97% rename from liveobjects/src/test/kotlin/io/ably/lib/liveobjects/unit/PathSegmentsTest.kt rename to liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/unit/PathSegmentsTest.kt index 31bd0f4bd..f1909b76e 100644 --- a/liveobjects/src/test/kotlin/io/ably/lib/liveobjects/unit/PathSegmentsTest.kt +++ b/liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/unit/PathSegmentsTest.kt @@ -1,6 +1,6 @@ -package io.ably.lib.liveobjects.unit +package io.ably.pubsub.liveobjects.unit -import io.ably.lib.liveobjects.path.PathSegments +import io.ably.pubsub.liveobjects.path.PathSegments import org.junit.Assert.assertEquals import org.junit.Test diff --git a/liveobjects/src/test/kotlin/io/ably/lib/liveobjects/unit/TestHelpers.kt b/liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/unit/TestHelpers.kt similarity index 68% rename from liveobjects/src/test/kotlin/io/ably/lib/liveobjects/unit/TestHelpers.kt rename to liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/unit/TestHelpers.kt index 1ccfbc66e..344451fdc 100644 --- a/liveobjects/src/test/kotlin/io/ably/lib/liveobjects/unit/TestHelpers.kt +++ b/liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/unit/TestHelpers.kt @@ -1,14 +1,14 @@ -package io.ably.lib.liveobjects.unit +package io.ably.pubsub.liveobjects.unit -import io.ably.lib.liveobjects.adapter.AblyClientAdapter -import io.ably.lib.liveobjects.connectionManager -import io.ably.lib.realtime.AblyRealtime -import io.ably.lib.realtime.Channel -import io.ably.lib.realtime.ChannelState -import io.ably.lib.transport.ConnectionManager -import io.ably.lib.types.ChannelMode -import io.ably.lib.types.ChannelOptions -import io.ably.lib.types.ClientOptions +import io.ably.pubsub.liveobjects.adapter.AblyClientAdapter +import io.ably.pubsub.liveobjects.connectionManager +import io.ably.pubsub.realtime.RealtimeClientFactory +import io.ably.pubsub.realtime.Channel +import io.ably.pubsub.realtime.ChannelState +import io.ably.pubsub.transport.ConnectionManager +import io.ably.pubsub.types.ChannelMode +import io.ably.pubsub.types.ChannelOptions +import io.ably.pubsub.types.ClientOptions import io.mockk.every import io.mockk.mockk import io.mockk.mockkStatic @@ -18,7 +18,7 @@ internal fun getMockRealtimeChannel( channelName: String, clientId: String = "client1", channelModes: Array = arrayOf(ChannelMode.object_publish, ChannelMode.object_subscribe)): Channel { - val client = AblyRealtime(ClientOptions().apply { + val client = RealtimeClientFactory.create(ClientOptions().apply { autoConnect = false key = "keyName:Value" this.clientId = clientId @@ -41,7 +41,7 @@ internal fun getMockRealtimeChannel( } internal fun getMockAblyClientAdapter(): AblyClientAdapter { - mockkStatic("io.ably.lib.liveobjects.HelpersKt") + mockkStatic("io.ably.pubsub.liveobjects.HelpersKt") return mockk(relaxed = true) { every { getChannel(any()) } returns getMockRealtimeChannel("testChannelName") every { connectionManager } returns mockk(relaxed = true) diff --git a/liveobjects/src/test/kotlin/io/ably/lib/liveobjects/unit/UtilsTest.kt b/liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/unit/UtilsTest.kt similarity index 89% rename from liveobjects/src/test/kotlin/io/ably/lib/liveobjects/unit/UtilsTest.kt rename to liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/unit/UtilsTest.kt index 169e72d9c..ee032ecf9 100644 --- a/liveobjects/src/test/kotlin/io/ably/lib/liveobjects/unit/UtilsTest.kt +++ b/liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/unit/UtilsTest.kt @@ -1,12 +1,12 @@ -package io.ably.lib.liveobjects.unit +package io.ably.pubsub.liveobjects.unit -import io.ably.lib.liveobjects.* -import io.ably.lib.liveobjects.ObjectErrorCode -import io.ably.lib.liveobjects.ObjectHttpStatusCode -import io.ably.lib.liveobjects.byteSize -import io.ably.lib.liveobjects.clientError -import io.ably.lib.liveobjects.generateNonce -import io.ably.lib.types.ErrorInfo +import io.ably.pubsub.liveobjects.* +import io.ably.pubsub.liveobjects.ObjectErrorCode +import io.ably.pubsub.liveobjects.ObjectHttpStatusCode +import io.ably.pubsub.liveobjects.byteSize +import io.ably.pubsub.liveobjects.clientError +import io.ably.pubsub.liveobjects.generateNonce +import io.ably.pubsub.types.ErrorInfo import org.junit.Test import org.junit.Assert.* diff --git a/liveobjects/src/test/kotlin/io/ably/lib/liveobjects/unit/fixtures/ObjectMessageFixtures.kt b/liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/unit/fixtures/ObjectMessageFixtures.kt similarity index 88% rename from liveobjects/src/test/kotlin/io/ably/lib/liveobjects/unit/fixtures/ObjectMessageFixtures.kt rename to liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/unit/fixtures/ObjectMessageFixtures.kt index 5fcccf56d..3d316d9e4 100644 --- a/liveobjects/src/test/kotlin/io/ably/lib/liveobjects/unit/fixtures/ObjectMessageFixtures.kt +++ b/liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/unit/fixtures/ObjectMessageFixtures.kt @@ -1,19 +1,19 @@ -package io.ably.lib.liveobjects.unit.fixtures +package io.ably.pubsub.liveobjects.unit.fixtures import com.google.gson.JsonArray import com.google.gson.JsonObject -import io.ably.lib.liveobjects.message.WireMapCreate -import io.ably.lib.liveobjects.message.WireMapCreateWithObjectId -import io.ably.lib.liveobjects.message.WireMapSet -import io.ably.lib.liveobjects.message.WireObjectData -import io.ably.lib.liveobjects.message.WireObjectMessage -import io.ably.lib.liveobjects.message.WireObjectOperation -import io.ably.lib.liveobjects.message.WireObjectOperationAction -import io.ably.lib.liveobjects.message.WireObjectState -import io.ably.lib.liveobjects.message.WireObjectsCounter -import io.ably.lib.liveobjects.message.WireObjectsMap -import io.ably.lib.liveobjects.message.WireObjectsMapEntry -import io.ably.lib.liveobjects.message.WireObjectsMapSemantics +import io.ably.pubsub.liveobjects.message.WireMapCreate +import io.ably.pubsub.liveobjects.message.WireMapCreateWithObjectId +import io.ably.pubsub.liveobjects.message.WireMapSet +import io.ably.pubsub.liveobjects.message.WireObjectData +import io.ably.pubsub.liveobjects.message.WireObjectMessage +import io.ably.pubsub.liveobjects.message.WireObjectOperation +import io.ably.pubsub.liveobjects.message.WireObjectOperationAction +import io.ably.pubsub.liveobjects.message.WireObjectState +import io.ably.pubsub.liveobjects.message.WireObjectsCounter +import io.ably.pubsub.liveobjects.message.WireObjectsMap +import io.ably.pubsub.liveobjects.message.WireObjectsMapEntry +import io.ably.pubsub.liveobjects.message.WireObjectsMapSemantics import java.util.Base64 internal val dummyObjectDataStringValue = WireObjectData(objectId = "object-id", string = "dummy string") diff --git a/liveobjects/src/test/kotlin/io/ably/lib/liveobjects/uts/README.md b/liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/uts/README.md similarity index 72% rename from liveobjects/src/test/kotlin/io/ably/lib/liveobjects/uts/README.md rename to liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/uts/README.md index 415c605ef..9af069f99 100644 --- a/liveobjects/src/test/kotlin/io/ably/lib/liveobjects/uts/README.md +++ b/liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/uts/README.md @@ -5,9 +5,9 @@ objects tiers live here in `:liveobjects`'s own test source set: | Tier | Package | Run with | |---|---|---| -| unit | `io.ably.lib.liveobjects.uts.unit` | `./gradlew :liveobjects:runLiveObjectsUnitTests` | -| integration (direct sandbox) | `io.ably.lib.liveobjects.uts.integration` | `./gradlew :liveobjects:runLiveObjectsIntegrationTests` | -| proxy | `io.ably.lib.liveobjects.uts.proxy` | `./gradlew :liveobjects:runLiveObjectsIntegrationTests` | +| unit | `io.ably.pubsub.liveobjects.uts.unit` | `./gradlew :liveobjects:runLiveObjectsUnitTests` | +| integration (direct sandbox) | `io.ably.pubsub.liveobjects.uts.integration` | `./gradlew :liveobjects:runLiveObjectsIntegrationTests` | +| proxy | `io.ably.pubsub.liveobjects.uts.proxy` | `./gradlew :liveobjects:runLiveObjectsIntegrationTests` | (`runLiveObjectsIntegrationTests` covers **both** the `integration` and `proxy` packages.) @@ -16,9 +16,9 @@ objects tiers live here in `:liveobjects`'s own test source set: - **Convention:** public-tier spec tests use only the public API + the tier's `Helpers.kt`; only the five internal-graph unit specs (`internal_live_counter`, `internal_live_map`, `object_id`, `objects_pool`, `parent_references`) and documented deviations may reference - `io.ably.lib.liveobjects` internals. -- Transport bootstrap comes from the shared `:uts` infra (`io.ably.lib.uts.infra.*`, consumed via + `io.ably.pubsub.liveobjects` internals. +- Transport bootstrap comes from the shared `:uts` infra (`io.ably.pubsub.uts.infra.*`, consumed via `testImplementation(project(":uts"))`); message builders are the typed `Wire*` constructions in each tier's `Helpers.kt` (`unit/Helpers.kt`, `integration/Helpers.kt`). - Deviations for all three tiers are recorded in [`deviations.md`](deviations.md) (same discipline as - the realtime/rest tiers' `:java`-hosted `lib/src/test/kotlin/io/ably/lib/uts/deviations.md`). + the realtime/rest tiers' `:java`-hosted `lib/src/test/kotlin/io/ably/pubsub/uts/deviations.md`). diff --git a/liveobjects/src/test/kotlin/io/ably/lib/liveobjects/uts/deviations.md b/liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/uts/deviations.md similarity index 98% rename from liveobjects/src/test/kotlin/io/ably/lib/liveobjects/uts/deviations.md rename to liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/uts/deviations.md index 3223ad755..65b823e77 100644 --- a/liveobjects/src/test/kotlin/io/ably/lib/liveobjects/uts/deviations.md +++ b/liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/uts/deviations.md @@ -1,15 +1,15 @@ -# Deviations — UTS objects suites (`io.ably.lib.liveobjects.uts.*`) +# Deviations — UTS objects suites (`io.ably.pubsub.liveobjects.uts.*`) > **Scope:** this file holds deviations for **all three objects tiers** now hosted in `:liveobjects` — -> objects **unit** (`io.ably.lib.liveobjects.uts.unit`), **integration** -> (`io.ably.lib.liveobjects.uts.integration`) and **proxy** (`io.ably.lib.liveobjects.uts.proxy`). +> objects **unit** (`io.ably.pubsub.liveobjects.uts.unit`), **integration** +> (`io.ably.pubsub.liveobjects.uts.integration`) and **proxy** (`io.ably.pubsub.liveobjects.uts.proxy`). > The integration/proxy tiers moved here from `:uts` in Phase 3 alongside the tests they document. > > Records every place a generated test deviates from its UTS spec, using the manual's > **Recording deviations** entry format. Structural deviation vocabulary for these suites: > S-1…S-4 in `.claude/skills/uts-to-kotlin/references/objects-mapping.md` §17.9. > (The realtime/rest tiers keep their own file, `:java`-hosted, at -> `lib/src/test/kotlin/io/ably/lib/uts/deviations.md`.) +> `lib/src/test/kotlin/io/ably/pubsub/uts/deviations.md`.) ## UTS Spec Errors diff --git a/liveobjects/src/test/kotlin/io/ably/lib/liveobjects/uts/integration/Helpers.kt b/liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/uts/integration/Helpers.kt similarity index 88% rename from liveobjects/src/test/kotlin/io/ably/lib/liveobjects/uts/integration/Helpers.kt rename to liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/uts/integration/Helpers.kt index f90442881..dcc61d3c7 100644 --- a/liveobjects/src/test/kotlin/io/ably/lib/liveobjects/uts/integration/Helpers.kt +++ b/liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/uts/integration/Helpers.kt @@ -1,12 +1,12 @@ -package io.ably.lib.liveobjects.uts.integration +package io.ably.pubsub.liveobjects.uts.integration import com.google.gson.JsonArray import com.google.gson.JsonElement import com.google.gson.JsonObject -import io.ably.lib.http.HttpUtils -import io.ably.lib.rest.AblyRest -import io.ably.lib.types.ClientOptions -import io.ably.lib.uts.infra.integration.SandboxApp +import io.ably.pubsub.http.HttpUtils +import io.ably.pubsub.http.HttpClientFactory +import io.ably.pubsub.types.ClientOptions +import io.ably.pubsub.uts.infra.integration.SandboxApp /** * LiveObjects **integration** test helpers — the ably-java translation of the UTS @@ -19,7 +19,7 @@ import io.ably.lib.uts.infra.integration.SandboxApp * The source of truth for the request shape is the published OpenAPI * (`ably-docs/static/open-specs/liveobjects.yaml`, "Update LiveObjects REST API docs for **V2 format**", * 2026-01-22), **not** the UTS pseudocode — the UTS spec helper describes a legacy/pre-V2 shape that is out - * of sync (see [provisionObjectsViaRest]). The V2 contract: + * of sync (see [provisionObjectsViaHttp]). The V2 contract: * * - Endpoint: `POST /channels/{channel}/object` (**singular** `object`). * - Body: a single operation object, **or** a bare JSON array of them — there is **no** `{ "messages": [...] }` @@ -30,7 +30,7 @@ import io.ably.lib.uts.infra.integration.SandboxApp * - Values are `{ string }` / `{ number }` / `{ boolean }` / `{ bytes }`(base64) / `{ objectId }`. * - `mapCreate.semantics` is the integer `0` (LWW); its `entries` wrap each value as `{ "data": }`. * - * Compiles against `:java` only (`AblyRest` + `HttpUtils`), like the unit `Helpers.kt`. + * Compiles against `:core` only (`HttpClientFactory` + `HttpUtils`), like the unit `Helpers.kt`. */ // --------------------------------------------------------------------------- @@ -117,17 +117,15 @@ fun counterIncOp(number: Number, objectId: String? = null, path: String? = null, * * @return the `objectIds` reported by the API for the created/updated objects. */ -fun provisionObjectsViaRest(apiKey: String, channelName: String, operations: List): List { +fun provisionObjectsViaHttp(apiKey: String, channelName: String, operations: List): List { require(operations.isNotEmpty()) { "operations must not be empty" } - val rest = AblyRest( + val rest = HttpClientFactory.create( ClientOptions().apply { key = apiKey - // Target the same nonprod sandbox host that SandboxApp and the realtime clients use - // (sandbox.realtime.ably-nonprod.net) — NOT environment="sandbox", which resolves to the - // legacy prod-sandbox host sandbox-rest.ably.io (Hosts.java also forbids setting both - // environment and restHost). Matches standard_test_pool.md (ably/specification#497). - restHost = SandboxApp.sandboxHost + // Target the same nonprod sandbox endpoint that SandboxApp and the realtime clients use. + // Matches standard_test_pool.md (ably/specification#497). + endpoint = SandboxApp.sandboxEndpoint useBinaryProtocol = false }, ) diff --git a/liveobjects/src/test/kotlin/io/ably/lib/liveobjects/uts/integration/ObjectsLifecycleTest.kt b/liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/uts/integration/ObjectsLifecycleTest.kt similarity index 90% rename from liveobjects/src/test/kotlin/io/ably/lib/liveobjects/uts/integration/ObjectsLifecycleTest.kt rename to liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/uts/integration/ObjectsLifecycleTest.kt index ea3456aa2..10faaab84 100644 --- a/liveobjects/src/test/kotlin/io/ably/lib/liveobjects/uts/integration/ObjectsLifecycleTest.kt +++ b/liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/uts/integration/ObjectsLifecycleTest.kt @@ -1,20 +1,20 @@ -package io.ably.lib.liveobjects.uts.integration - -import io.ably.lib.liveobjects.path.PathObject -import io.ably.lib.liveobjects.path.PathObjectListener -import io.ably.lib.liveobjects.path.PathObjectSubscriptionEvent -import io.ably.lib.liveobjects.value.LiveCounter -import io.ably.lib.liveobjects.value.LiveMap -import io.ably.lib.liveobjects.value.LiveMapValue -import io.ably.lib.realtime.AblyRealtime -import io.ably.lib.realtime.Channel -import io.ably.lib.realtime.ConnectionState -import io.ably.lib.types.ChannelMode -import io.ably.lib.types.ChannelOptions -import io.ably.lib.uts.infra.awaitState -import io.ably.lib.uts.infra.integration.SandboxApp -import io.ably.lib.uts.infra.pollUntil -import io.ably.lib.uts.infra.unit.TestRealtimeClient +package io.ably.pubsub.liveobjects.uts.integration + +import io.ably.pubsub.liveobjects.path.PathObject +import io.ably.pubsub.liveobjects.path.PathObjectListener +import io.ably.pubsub.liveobjects.path.PathObjectSubscriptionEvent +import io.ably.pubsub.liveobjects.value.LiveCounter +import io.ably.pubsub.liveobjects.value.LiveMap +import io.ably.pubsub.liveobjects.value.LiveMapValue +import io.ably.pubsub.realtime.PubSubRealtimeClient +import io.ably.pubsub.realtime.Channel +import io.ably.pubsub.realtime.ConnectionState +import io.ably.pubsub.types.ChannelMode +import io.ably.pubsub.types.ChannelOptions +import io.ably.pubsub.uts.infra.awaitState +import io.ably.pubsub.uts.infra.integration.SandboxApp +import io.ably.pubsub.uts.infra.pollUntil +import io.ably.pubsub.uts.infra.unit.TestRealtimeClient import kotlinx.coroutines.future.await import kotlinx.coroutines.runBlocking import kotlinx.coroutines.test.runTest @@ -234,10 +234,10 @@ class ObjectsLifecycleTest { val channelName = "objects-rest-provision-" + UUID.randomUUID() // Provision data via REST before any realtime client connects (see Helpers.kt). - // Both provisionObjectsViaRest and the realtime client below target the same nonprod + // Both provisionObjectsViaHttp and the realtime client below target the same nonprod // sandbox host (SandboxApp.sandboxHost), so the provisioned data is visible // to the client once the SDK's OBJECT_SYNC + RealtimeObject.get() land. - provisionObjectsViaRest( + provisionObjectsViaHttp( app.defaultKey, channelName, listOf(mapSetOp("provisioned", valueString("from_rest"), objectId = "root")), @@ -259,16 +259,15 @@ class ObjectsLifecycleTest { // ── helpers ────────────────────────────────────────────────────────────── /** A realtime client wired straight to the nonprod sandbox (no proxy). */ - private fun newClient(useBinaryProtocol: Boolean): AblyRealtime = TestRealtimeClient { + private fun newClient(useBinaryProtocol: Boolean): PubSubRealtimeClient = TestRealtimeClient { key = app.defaultKey - realtimeHost = SandboxApp.sandboxHost - restHost = SandboxApp.sandboxHost + endpoint = SandboxApp.sandboxEndpoint this.useBinaryProtocol = useBinaryProtocol autoConnect = false } /** A channel with the object modes (defaults to OBJECT_SUBSCRIBE + OBJECT_PUBLISH). */ - private fun objectChannel(client: AblyRealtime, name: String, vararg modes: ChannelMode): Channel = + private fun objectChannel(client: PubSubRealtimeClient, name: String, vararg modes: ChannelMode): Channel = client.channels.get( name, ChannelOptions().apply { diff --git a/liveobjects/src/test/kotlin/io/ably/lib/liveobjects/uts/integration/ObjectsSyncTest.kt b/liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/uts/integration/ObjectsSyncTest.kt similarity index 87% rename from liveobjects/src/test/kotlin/io/ably/lib/liveobjects/uts/integration/ObjectsSyncTest.kt rename to liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/uts/integration/ObjectsSyncTest.kt index 8c7b90bff..a3e8bb923 100644 --- a/liveobjects/src/test/kotlin/io/ably/lib/liveobjects/uts/integration/ObjectsSyncTest.kt +++ b/liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/uts/integration/ObjectsSyncTest.kt @@ -1,18 +1,18 @@ -package io.ably.lib.liveobjects.uts.integration - -import io.ably.lib.liveobjects.path.PathObject -import io.ably.lib.liveobjects.value.LiveMapValue -import io.ably.lib.realtime.AblyRealtime -import io.ably.lib.realtime.Channel -import io.ably.lib.realtime.ChannelState -import io.ably.lib.realtime.ConnectionState -import io.ably.lib.types.ChannelMode -import io.ably.lib.types.ChannelOptions -import io.ably.lib.uts.infra.awaitChannelState -import io.ably.lib.uts.infra.awaitState -import io.ably.lib.uts.infra.integration.SandboxApp -import io.ably.lib.uts.infra.pollUntil -import io.ably.lib.uts.infra.unit.TestRealtimeClient +package io.ably.pubsub.liveobjects.uts.integration + +import io.ably.pubsub.liveobjects.path.PathObject +import io.ably.pubsub.liveobjects.value.LiveMapValue +import io.ably.pubsub.realtime.PubSubRealtimeClient +import io.ably.pubsub.realtime.Channel +import io.ably.pubsub.realtime.ChannelState +import io.ably.pubsub.realtime.ConnectionState +import io.ably.pubsub.types.ChannelMode +import io.ably.pubsub.types.ChannelOptions +import io.ably.pubsub.uts.infra.awaitChannelState +import io.ably.pubsub.uts.infra.awaitState +import io.ably.pubsub.uts.infra.integration.SandboxApp +import io.ably.pubsub.uts.infra.pollUntil +import io.ably.pubsub.uts.infra.unit.TestRealtimeClient import kotlinx.coroutines.future.await import kotlinx.coroutines.runBlocking import kotlinx.coroutines.test.runTest @@ -168,16 +168,15 @@ class ObjectsSyncTest { // ── helpers ────────────────────────────────────────────────────────────── /** A realtime client wired straight to the nonprod sandbox (no proxy). */ - private fun newClient(useBinaryProtocol: Boolean): AblyRealtime = TestRealtimeClient { + private fun newClient(useBinaryProtocol: Boolean): PubSubRealtimeClient = TestRealtimeClient { key = app.defaultKey - realtimeHost = SandboxApp.sandboxHost - restHost = SandboxApp.sandboxHost + endpoint = SandboxApp.sandboxEndpoint this.useBinaryProtocol = useBinaryProtocol autoConnect = false } /** A channel with the object modes (defaults to OBJECT_SUBSCRIBE + OBJECT_PUBLISH). */ - private fun objectChannel(client: AblyRealtime, name: String, vararg modes: ChannelMode): Channel = + private fun objectChannel(client: PubSubRealtimeClient, name: String, vararg modes: ChannelMode): Channel = client.channels.get( name, ChannelOptions().apply { diff --git a/liveobjects/src/test/kotlin/io/ably/lib/liveobjects/uts/proxy/ObjectsFaultsTest.kt b/liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/uts/proxy/ObjectsFaultsTest.kt similarity index 92% rename from liveobjects/src/test/kotlin/io/ably/lib/liveobjects/uts/proxy/ObjectsFaultsTest.kt rename to liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/uts/proxy/ObjectsFaultsTest.kt index 7532ffac1..049a19417 100644 --- a/liveobjects/src/test/kotlin/io/ably/lib/liveobjects/uts/proxy/ObjectsFaultsTest.kt +++ b/liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/uts/proxy/ObjectsFaultsTest.kt @@ -1,31 +1,31 @@ -package io.ably.lib.liveobjects.uts.proxy - -import io.ably.lib.liveobjects.path.PathObject -import io.ably.lib.liveobjects.value.LiveMapValue -import io.ably.lib.realtime.AblyRealtime -import io.ably.lib.types.AblyException -import io.ably.lib.realtime.Channel -import io.ably.lib.realtime.ChannelState -import io.ably.lib.realtime.ConnectionState -import io.ably.lib.realtime.ConnectionStateListener -import io.ably.lib.types.ChannelMode -import io.ably.lib.types.ChannelOptions -import io.ably.lib.uts.infra.awaitChannelState -import io.ably.lib.uts.infra.awaitState -import io.ably.lib.uts.infra.integration.SandboxApp -import io.ably.lib.uts.infra.integration.proxy.ProxyManager -import io.ably.lib.uts.infra.integration.proxy.ProxySession -import io.ably.lib.uts.infra.integration.proxy.connectThroughProxy -import io.ably.lib.uts.infra.integration.proxy.wsFrameToClientRule -import io.ably.lib.uts.infra.pollUntil -import io.ably.lib.uts.infra.unit.TestRealtimeClient +package io.ably.pubsub.liveobjects.uts.proxy + +import io.ably.pubsub.liveobjects.path.PathObject +import io.ably.pubsub.liveobjects.value.LiveMapValue +import io.ably.pubsub.realtime.PubSubRealtimeClient +import io.ably.pubsub.types.AblyException +import io.ably.pubsub.realtime.Channel +import io.ably.pubsub.realtime.ChannelState +import io.ably.pubsub.realtime.ConnectionState +import io.ably.pubsub.realtime.ConnectionStateListener +import io.ably.pubsub.types.ChannelMode +import io.ably.pubsub.types.ChannelOptions +import io.ably.pubsub.uts.infra.awaitChannelState +import io.ably.pubsub.uts.infra.awaitState +import io.ably.pubsub.uts.infra.integration.SandboxApp +import io.ably.pubsub.uts.infra.integration.proxy.ProxyManager +import io.ably.pubsub.uts.infra.integration.proxy.ProxySession +import io.ably.pubsub.uts.infra.integration.proxy.connectThroughProxy +import io.ably.pubsub.uts.infra.integration.proxy.wsFrameToClientRule +import io.ably.pubsub.uts.infra.pollUntil +import io.ably.pubsub.uts.infra.unit.TestRealtimeClient import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.delay import kotlinx.coroutines.future.await import kotlinx.coroutines.withContext import kotlinx.coroutines.runBlocking import kotlinx.coroutines.test.runTest -import io.ably.lib.uts.infra.withRealTimeout +import io.ably.pubsub.uts.infra.withRealTimeout import org.junit.jupiter.api.AfterAll import org.junit.jupiter.api.BeforeAll import org.junit.jupiter.api.Test @@ -353,7 +353,7 @@ class ObjectsFaultsTest { * (connected/connecting/disconnected), await CLOSED so the transport is torn down before * the proxy session is deleted. Wrapped in runCatching so cleanup never masks a test failure. */ - private suspend fun closeClient(client: AblyRealtime) { + private suspend fun closeClient(client: PubSubRealtimeClient) { val awaitClosed = client.connection.state in setOf( ConnectionState.connected, ConnectionState.connecting, ConnectionState.disconnected, ) @@ -362,22 +362,21 @@ class ObjectsFaultsTest { } /** A realtime client routed through the proxy (localhost hop → nonprod sandbox upstream). */ - private fun proxyClient(session: ProxySession): AblyRealtime = TestRealtimeClient { + private fun proxyClient(session: ProxySession): PubSubRealtimeClient = TestRealtimeClient { key = app.defaultKey connectThroughProxy(session) autoConnect = false } /** A realtime client connected straight to the nonprod sandbox (no proxy). */ - private fun directClient(): AblyRealtime = TestRealtimeClient { + private fun directClient(): PubSubRealtimeClient = TestRealtimeClient { key = app.defaultKey - realtimeHost = SandboxApp.sandboxHost - restHost = SandboxApp.sandboxHost + endpoint = SandboxApp.sandboxEndpoint autoConnect = false } /** A channel with the OBJECT_SUBSCRIBE + OBJECT_PUBLISH modes. */ - private fun objectChannel(client: AblyRealtime, name: String): Channel = + private fun objectChannel(client: PubSubRealtimeClient, name: String): Channel = client.channels.get( name, ChannelOptions().apply { diff --git a/liveobjects/src/test/kotlin/io/ably/lib/liveobjects/uts/unit/Helpers.kt b/liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/uts/unit/Helpers.kt similarity index 91% rename from liveobjects/src/test/kotlin/io/ably/lib/liveobjects/uts/unit/Helpers.kt rename to liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/uts/unit/Helpers.kt index 71d440aad..f4d9f733d 100644 --- a/liveobjects/src/test/kotlin/io/ably/lib/liveobjects/uts/unit/Helpers.kt +++ b/liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/uts/unit/Helpers.kt @@ -1,37 +1,37 @@ -package io.ably.lib.liveobjects.uts.unit +package io.ably.pubsub.liveobjects.uts.unit import com.google.gson.JsonElement import com.google.gson.JsonParser -import io.ably.lib.liveobjects.message.ObjectMessage -import io.ably.lib.liveobjects.message.WireCounterCreate -import io.ably.lib.liveobjects.message.WireCounterInc -import io.ably.lib.liveobjects.message.WireMapCreate -import io.ably.lib.liveobjects.message.WireMapRemove -import io.ably.lib.liveobjects.message.WireMapSet -import io.ably.lib.liveobjects.message.WireMapClear -import io.ably.lib.liveobjects.message.WireObjectData -import io.ably.lib.liveobjects.message.WireObjectDelete -import io.ably.lib.liveobjects.message.WireObjectMessage -import io.ably.lib.liveobjects.message.WireObjectOperation -import io.ably.lib.liveobjects.message.WireObjectOperationAction -import io.ably.lib.liveobjects.message.WireObjectState -import io.ably.lib.liveobjects.message.WireObjectsCounter -import io.ably.lib.liveobjects.message.WireObjectsMap -import io.ably.lib.liveobjects.message.WireObjectsMapEntry -import io.ably.lib.liveobjects.message.WireObjectsMapSemantics -import io.ably.lib.liveobjects.message.toPublicMessage -import io.ably.lib.liveobjects.path.types.LiveMapPathObject -import io.ably.lib.realtime.AblyRealtime -import io.ably.lib.realtime.Channel -import io.ably.lib.types.ChannelMode -import io.ably.lib.types.ChannelOptions -import io.ably.lib.types.ProtocolMessage -import io.ably.lib.types.PublishResult -import io.ably.lib.uts.infra.unit.ConnectionDetails -import io.ably.lib.uts.infra.unit.MockEvent -import io.ably.lib.uts.infra.unit.MockHttpClient -import io.ably.lib.uts.infra.unit.MockWebSocket -import io.ably.lib.uts.infra.unit.TestRealtimeClient +import io.ably.pubsub.liveobjects.message.ObjectMessage +import io.ably.pubsub.liveobjects.message.WireCounterCreate +import io.ably.pubsub.liveobjects.message.WireCounterInc +import io.ably.pubsub.liveobjects.message.WireMapCreate +import io.ably.pubsub.liveobjects.message.WireMapRemove +import io.ably.pubsub.liveobjects.message.WireMapSet +import io.ably.pubsub.liveobjects.message.WireMapClear +import io.ably.pubsub.liveobjects.message.WireObjectData +import io.ably.pubsub.liveobjects.message.WireObjectDelete +import io.ably.pubsub.liveobjects.message.WireObjectMessage +import io.ably.pubsub.liveobjects.message.WireObjectOperation +import io.ably.pubsub.liveobjects.message.WireObjectOperationAction +import io.ably.pubsub.liveobjects.message.WireObjectState +import io.ably.pubsub.liveobjects.message.WireObjectsCounter +import io.ably.pubsub.liveobjects.message.WireObjectsMap +import io.ably.pubsub.liveobjects.message.WireObjectsMapEntry +import io.ably.pubsub.liveobjects.message.WireObjectsMapSemantics +import io.ably.pubsub.liveobjects.message.toPublicMessage +import io.ably.pubsub.liveobjects.path.types.LiveMapPathObject +import io.ably.pubsub.realtime.PubSubRealtimeClient +import io.ably.pubsub.realtime.Channel +import io.ably.pubsub.types.ChannelMode +import io.ably.pubsub.types.ChannelOptions +import io.ably.pubsub.types.ProtocolMessage +import io.ably.pubsub.types.PublishResult +import io.ably.pubsub.uts.infra.unit.ConnectionDetails +import io.ably.pubsub.uts.infra.unit.MockEvent +import io.ably.pubsub.uts.infra.unit.MockHttpClient +import io.ably.pubsub.uts.infra.unit.MockWebSocket +import io.ably.pubsub.uts.infra.unit.TestRealtimeClient import kotlinx.coroutines.future.await /** @@ -45,7 +45,7 @@ import kotlinx.coroutines.future.await * transport serializes [ProtocolMessage.state] through the SDK's own `ObjectJsonSerializer`, * so the typed messages are the single source of truth for the wire form. * - * The transport bootstrap uses the shared `:uts` fixtures (`io.ably.lib.uts.infra.unit.*`). + * The transport bootstrap uses the shared `:uts` fixtures (`io.ably.pubsub.uts.infra.unit.*`). */ // --------------------------------------------------------------------------- @@ -253,7 +253,7 @@ internal fun buildPublicObjectMessage(objectMessage: WireObjectMessage, channelN // `provision_objects_via_rest(...)` is intentionally not here — it's REST fixture provisioning for // *integration* tests and lives with this module's integration tier -// (io.ably.lib.liveobjects.uts.integration.Helpers). +// (io.ably.pubsub.liveobjects.uts.integration.Helpers). // --------------------------------------------------------------------------- // STANDARD_POOL_OBJECTS — the fixed tree shared by all objects unit specs @@ -312,7 +312,7 @@ internal val STANDARD_POOL_OBJECTS: List = listOf( /** Result of [setupSyncedChannel] — the spec's `{ client, channel, root, mock_ws }`. */ data class SyncedChannel( - val client: AblyRealtime, + val client: PubSubRealtimeClient, val channel: Channel, val root: LiveMapPathObject, val mockWs: MockWebSocket, diff --git a/liveobjects/src/test/kotlin/io/ably/lib/liveobjects/uts/unit/InstanceTest.kt b/liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/uts/unit/InstanceTest.kt similarity index 96% rename from liveobjects/src/test/kotlin/io/ably/lib/liveobjects/uts/unit/InstanceTest.kt rename to liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/uts/unit/InstanceTest.kt index 833f755cb..0b021146d 100644 --- a/liveobjects/src/test/kotlin/io/ably/lib/liveobjects/uts/unit/InstanceTest.kt +++ b/liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/uts/unit/InstanceTest.kt @@ -1,13 +1,13 @@ -package io.ably.lib.liveobjects.uts.unit - -import io.ably.lib.liveobjects.Subscription -import io.ably.lib.liveobjects.ValueType -import io.ably.lib.liveobjects.instance.Instance -import io.ably.lib.liveobjects.instance.InstanceListener -import io.ably.lib.liveobjects.instance.InstanceSubscriptionEvent -import io.ably.lib.liveobjects.message.ObjectOperationAction -import io.ably.lib.liveobjects.value.LiveMapValue -import io.ably.lib.uts.infra.pollUntil +package io.ably.pubsub.liveobjects.uts.unit + +import io.ably.pubsub.liveobjects.Subscription +import io.ably.pubsub.liveobjects.ValueType +import io.ably.pubsub.liveobjects.instance.Instance +import io.ably.pubsub.liveobjects.instance.InstanceListener +import io.ably.pubsub.liveobjects.instance.InstanceSubscriptionEvent +import io.ably.pubsub.liveobjects.message.ObjectOperationAction +import io.ably.pubsub.liveobjects.value.LiveMapValue +import io.ably.pubsub.uts.infra.pollUntil import kotlinx.coroutines.future.await import kotlinx.coroutines.test.runTest import kotlin.test.Test diff --git a/liveobjects/src/test/kotlin/io/ably/lib/liveobjects/uts/unit/InternalLiveCounterApiTest.kt b/liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/uts/unit/InternalLiveCounterApiTest.kt similarity index 92% rename from liveobjects/src/test/kotlin/io/ably/lib/liveobjects/uts/unit/InternalLiveCounterApiTest.kt rename to liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/uts/unit/InternalLiveCounterApiTest.kt index d3aa6337d..560cb1cf1 100644 --- a/liveobjects/src/test/kotlin/io/ably/lib/liveobjects/uts/unit/InternalLiveCounterApiTest.kt +++ b/liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/uts/unit/InternalLiveCounterApiTest.kt @@ -1,14 +1,14 @@ -package io.ably.lib.liveobjects.uts.unit - -import io.ably.lib.liveobjects.instance.InstanceListener -import io.ably.lib.liveobjects.instance.InstanceSubscriptionEvent -import io.ably.lib.liveobjects.message.WireObjectMessage -import io.ably.lib.liveobjects.message.WireObjectOperationAction -import io.ably.lib.types.AblyException -import io.ably.lib.types.ProtocolMessage -import io.ably.lib.uts.infra.pollUntil -import io.ably.lib.uts.infra.unit.MockEvent -import io.ably.lib.uts.infra.unit.MockWebSocket +package io.ably.pubsub.liveobjects.uts.unit + +import io.ably.pubsub.liveobjects.instance.InstanceListener +import io.ably.pubsub.liveobjects.instance.InstanceSubscriptionEvent +import io.ably.pubsub.liveobjects.message.WireObjectMessage +import io.ably.pubsub.liveobjects.message.WireObjectOperationAction +import io.ably.pubsub.types.AblyException +import io.ably.pubsub.types.ProtocolMessage +import io.ably.pubsub.uts.infra.pollUntil +import io.ably.pubsub.uts.infra.unit.MockEvent +import io.ably.pubsub.uts.infra.unit.MockWebSocket import kotlinx.coroutines.future.await import kotlinx.coroutines.test.runTest import kotlin.test.Test diff --git a/liveobjects/src/test/kotlin/io/ably/lib/liveobjects/uts/unit/InternalLiveCounterTest.kt b/liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/uts/unit/InternalLiveCounterTest.kt similarity index 96% rename from liveobjects/src/test/kotlin/io/ably/lib/liveobjects/uts/unit/InternalLiveCounterTest.kt rename to liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/uts/unit/InternalLiveCounterTest.kt index 4c02370a7..5b1a8587e 100644 --- a/liveobjects/src/test/kotlin/io/ably/lib/liveobjects/uts/unit/InternalLiveCounterTest.kt +++ b/liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/uts/unit/InternalLiveCounterTest.kt @@ -1,17 +1,17 @@ -package io.ably.lib.liveobjects.uts.unit - -import io.ably.lib.liveobjects.DefaultRealtimeObject -import io.ably.lib.liveobjects.ObjectsOperationSource -import io.ably.lib.liveobjects.message.WireCounterCreate -import io.ably.lib.liveobjects.message.WireCounterInc -import io.ably.lib.liveobjects.message.WireObjectMessage -import io.ably.lib.liveobjects.message.WireObjectOperation -import io.ably.lib.liveobjects.message.WireObjectOperationAction -import io.ably.lib.liveobjects.message.WireObjectsCounter -import io.ably.lib.liveobjects.unit.getMockAblyClientAdapter -import io.ably.lib.liveobjects.value.ObjectUpdate -import io.ably.lib.liveobjects.value.livecounter.InternalLiveCounter -import io.ably.lib.liveobjects.value.noOp +package io.ably.pubsub.liveobjects.uts.unit + +import io.ably.pubsub.liveobjects.DefaultRealtimeObject +import io.ably.pubsub.liveobjects.ObjectsOperationSource +import io.ably.pubsub.liveobjects.message.WireCounterCreate +import io.ably.pubsub.liveobjects.message.WireCounterInc +import io.ably.pubsub.liveobjects.message.WireObjectMessage +import io.ably.pubsub.liveobjects.message.WireObjectOperation +import io.ably.pubsub.liveobjects.message.WireObjectOperationAction +import io.ably.pubsub.liveobjects.message.WireObjectsCounter +import io.ably.pubsub.liveobjects.unit.getMockAblyClientAdapter +import io.ably.pubsub.liveobjects.value.ObjectUpdate +import io.ably.pubsub.liveobjects.value.livecounter.InternalLiveCounter +import io.ably.pubsub.liveobjects.value.noOp import io.mockk.unmockkAll import kotlin.test.AfterTest import kotlin.test.BeforeTest diff --git a/liveobjects/src/test/kotlin/io/ably/lib/liveobjects/uts/unit/InternalLiveMapApiTest.kt b/liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/uts/unit/InternalLiveMapApiTest.kt similarity index 96% rename from liveobjects/src/test/kotlin/io/ably/lib/liveobjects/uts/unit/InternalLiveMapApiTest.kt rename to liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/uts/unit/InternalLiveMapApiTest.kt index 6c132370a..0fc64f84c 100644 --- a/liveobjects/src/test/kotlin/io/ably/lib/liveobjects/uts/unit/InternalLiveMapApiTest.kt +++ b/liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/uts/unit/InternalLiveMapApiTest.kt @@ -1,14 +1,14 @@ -package io.ably.lib.liveobjects.uts.unit +package io.ably.pubsub.liveobjects.uts.unit import com.google.gson.JsonParser -import io.ably.lib.liveobjects.message.WireObjectMessage -import io.ably.lib.liveobjects.message.WireObjectOperationAction -import io.ably.lib.liveobjects.value.LiveCounter -import io.ably.lib.liveobjects.value.LiveMap -import io.ably.lib.liveobjects.value.LiveMapValue -import io.ably.lib.types.ProtocolMessage -import io.ably.lib.uts.infra.unit.MockEvent -import io.ably.lib.uts.infra.unit.MockWebSocket +import io.ably.pubsub.liveobjects.message.WireObjectMessage +import io.ably.pubsub.liveobjects.message.WireObjectOperationAction +import io.ably.pubsub.liveobjects.value.LiveCounter +import io.ably.pubsub.liveobjects.value.LiveMap +import io.ably.pubsub.liveobjects.value.LiveMapValue +import io.ably.pubsub.types.ProtocolMessage +import io.ably.pubsub.uts.infra.unit.MockEvent +import io.ably.pubsub.uts.infra.unit.MockWebSocket import kotlinx.coroutines.future.await import kotlinx.coroutines.test.runTest import kotlin.test.Test diff --git a/liveobjects/src/test/kotlin/io/ably/lib/liveobjects/uts/unit/InternalLiveMapTest.kt b/liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/uts/unit/InternalLiveMapTest.kt similarity index 97% rename from liveobjects/src/test/kotlin/io/ably/lib/liveobjects/uts/unit/InternalLiveMapTest.kt rename to liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/uts/unit/InternalLiveMapTest.kt index 383c30586..75a8ac85e 100644 --- a/liveobjects/src/test/kotlin/io/ably/lib/liveobjects/uts/unit/InternalLiveMapTest.kt +++ b/liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/uts/unit/InternalLiveMapTest.kt @@ -1,20 +1,20 @@ -package io.ably.lib.liveobjects.uts.unit - -import io.ably.lib.liveobjects.DefaultRealtimeObject -import io.ably.lib.liveobjects.ObjectsOperationSource -import io.ably.lib.liveobjects.message.WireMapCreate -import io.ably.lib.liveobjects.message.WireObjectsMapSemantics -import io.ably.lib.liveobjects.unit.getMockAblyClientAdapter -import io.ably.lib.liveobjects.value.ObjectUpdate -import io.ably.lib.liveobjects.value.livecounter.InternalLiveCounter -import io.ably.lib.liveobjects.value.livemap.InternalLiveMap -import io.ably.lib.liveobjects.value.livemap.LiveMapEntry -import io.ably.lib.liveobjects.value.livemap.LiveMapManager -import io.ably.lib.liveobjects.value.livemap.MapChange -import io.ably.lib.liveobjects.value.livemap.isEntryOrRefTombstoned -import io.ably.lib.liveobjects.value.noOp -import io.ably.lib.util.Clock -import io.ably.lib.util.SystemClock +package io.ably.pubsub.liveobjects.uts.unit + +import io.ably.pubsub.liveobjects.DefaultRealtimeObject +import io.ably.pubsub.liveobjects.ObjectsOperationSource +import io.ably.pubsub.liveobjects.message.WireMapCreate +import io.ably.pubsub.liveobjects.message.WireObjectsMapSemantics +import io.ably.pubsub.liveobjects.unit.getMockAblyClientAdapter +import io.ably.pubsub.liveobjects.value.ObjectUpdate +import io.ably.pubsub.liveobjects.value.livecounter.InternalLiveCounter +import io.ably.pubsub.liveobjects.value.livemap.InternalLiveMap +import io.ably.pubsub.liveobjects.value.livemap.LiveMapEntry +import io.ably.pubsub.liveobjects.value.livemap.LiveMapManager +import io.ably.pubsub.liveobjects.value.livemap.MapChange +import io.ably.pubsub.liveobjects.value.livemap.isEntryOrRefTombstoned +import io.ably.pubsub.liveobjects.value.noOp +import io.ably.pubsub.util.Clock +import io.ably.pubsub.util.SystemClock import io.mockk.every import io.mockk.mockk import io.mockk.mockkStatic diff --git a/liveobjects/src/test/kotlin/io/ably/lib/liveobjects/uts/unit/LiveObjectSubscribeTest.kt b/liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/uts/unit/LiveObjectSubscribeTest.kt similarity index 96% rename from liveobjects/src/test/kotlin/io/ably/lib/liveobjects/uts/unit/LiveObjectSubscribeTest.kt rename to liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/uts/unit/LiveObjectSubscribeTest.kt index e95529fdc..26a997cae 100644 --- a/liveobjects/src/test/kotlin/io/ably/lib/liveobjects/uts/unit/LiveObjectSubscribeTest.kt +++ b/liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/uts/unit/LiveObjectSubscribeTest.kt @@ -1,14 +1,14 @@ -package io.ably.lib.liveobjects.uts.unit - -import io.ably.lib.liveobjects.Subscription -import io.ably.lib.liveobjects.instance.InstanceListener -import io.ably.lib.liveobjects.instance.InstanceSubscriptionEvent -import io.ably.lib.liveobjects.message.ObjectOperationAction -import io.ably.lib.liveobjects.message.WireCounterInc -import io.ably.lib.liveobjects.message.WireObjectMessage -import io.ably.lib.liveobjects.message.WireObjectOperation -import io.ably.lib.liveobjects.message.WireObjectOperationAction -import io.ably.lib.uts.infra.pollUntil +package io.ably.pubsub.liveobjects.uts.unit + +import io.ably.pubsub.liveobjects.Subscription +import io.ably.pubsub.liveobjects.instance.InstanceListener +import io.ably.pubsub.liveobjects.instance.InstanceSubscriptionEvent +import io.ably.pubsub.liveobjects.message.ObjectOperationAction +import io.ably.pubsub.liveobjects.message.WireCounterInc +import io.ably.pubsub.liveobjects.message.WireObjectMessage +import io.ably.pubsub.liveobjects.message.WireObjectOperation +import io.ably.pubsub.liveobjects.message.WireObjectOperationAction +import io.ably.pubsub.uts.infra.pollUntil import kotlinx.coroutines.test.runTest import kotlin.test.Test import kotlin.test.assertEquals diff --git a/liveobjects/src/test/kotlin/io/ably/lib/liveobjects/uts/unit/ObjectIdTest.kt b/liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/uts/unit/ObjectIdTest.kt similarity index 97% rename from liveobjects/src/test/kotlin/io/ably/lib/liveobjects/uts/unit/ObjectIdTest.kt rename to liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/uts/unit/ObjectIdTest.kt index a7ad64566..e7b4a385c 100644 --- a/liveobjects/src/test/kotlin/io/ably/lib/liveobjects/uts/unit/ObjectIdTest.kt +++ b/liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/uts/unit/ObjectIdTest.kt @@ -1,7 +1,7 @@ -package io.ably.lib.liveobjects.uts.unit +package io.ably.pubsub.liveobjects.uts.unit -import io.ably.lib.liveobjects.ObjectId -import io.ably.lib.liveobjects.value.ObjectType +import io.ably.pubsub.liveobjects.ObjectId +import io.ably.pubsub.liveobjects.value.ObjectType import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertFalse diff --git a/liveobjects/src/test/kotlin/io/ably/lib/liveobjects/uts/unit/ObjectsPoolTest.kt b/liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/uts/unit/ObjectsPoolTest.kt similarity index 97% rename from liveobjects/src/test/kotlin/io/ably/lib/liveobjects/uts/unit/ObjectsPoolTest.kt rename to liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/uts/unit/ObjectsPoolTest.kt index 4bc73fe01..53db2dd2c 100644 --- a/liveobjects/src/test/kotlin/io/ably/lib/liveobjects/uts/unit/ObjectsPoolTest.kt +++ b/liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/uts/unit/ObjectsPoolTest.kt @@ -1,18 +1,18 @@ -package io.ably.lib.liveobjects.uts.unit - -import io.ably.lib.liveobjects.DefaultRealtimeObject -import io.ably.lib.liveobjects.ObjectsOperationSource -import io.ably.lib.liveobjects.ObjectsState -import io.ably.lib.liveobjects.ROOT_OBJECT_ID -import io.ably.lib.liveobjects.instance.InstanceListener -import io.ably.lib.liveobjects.instance.InstanceSubscriptionEvent -import io.ably.lib.liveobjects.message.WireObjectMessage -import io.ably.lib.liveobjects.message.WireObjectOperation -import io.ably.lib.liveobjects.message.WireObjectOperationAction -import io.ably.lib.liveobjects.unit.getMockAblyClientAdapter -import io.ably.lib.liveobjects.value.livecounter.InternalLiveCounter -import io.ably.lib.liveobjects.value.livemap.InternalLiveMap -import io.ably.lib.liveobjects.value.livemap.LiveMapEntry +package io.ably.pubsub.liveobjects.uts.unit + +import io.ably.pubsub.liveobjects.DefaultRealtimeObject +import io.ably.pubsub.liveobjects.ObjectsOperationSource +import io.ably.pubsub.liveobjects.ObjectsState +import io.ably.pubsub.liveobjects.ROOT_OBJECT_ID +import io.ably.pubsub.liveobjects.instance.InstanceListener +import io.ably.pubsub.liveobjects.instance.InstanceSubscriptionEvent +import io.ably.pubsub.liveobjects.message.WireObjectMessage +import io.ably.pubsub.liveobjects.message.WireObjectOperation +import io.ably.pubsub.liveobjects.message.WireObjectOperationAction +import io.ably.pubsub.liveobjects.unit.getMockAblyClientAdapter +import io.ably.pubsub.liveobjects.value.livecounter.InternalLiveCounter +import io.ably.pubsub.liveobjects.value.livemap.InternalLiveMap +import io.ably.pubsub.liveobjects.value.livemap.LiveMapEntry import io.mockk.unmockkAll import kotlin.test.AfterTest import kotlin.test.BeforeTest diff --git a/liveobjects/src/test/kotlin/io/ably/lib/liveobjects/uts/unit/ParentReferencesTest.kt b/liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/uts/unit/ParentReferencesTest.kt similarity index 97% rename from liveobjects/src/test/kotlin/io/ably/lib/liveobjects/uts/unit/ParentReferencesTest.kt rename to liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/uts/unit/ParentReferencesTest.kt index 9ad6e08c6..34b74acf8 100644 --- a/liveobjects/src/test/kotlin/io/ably/lib/liveobjects/uts/unit/ParentReferencesTest.kt +++ b/liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/uts/unit/ParentReferencesTest.kt @@ -1,13 +1,13 @@ -package io.ably.lib.liveobjects.uts.unit - -import io.ably.lib.liveobjects.DefaultRealtimeObject -import io.ably.lib.liveobjects.ObjectsState -import io.ably.lib.liveobjects.ROOT_OBJECT_ID -import io.ably.lib.liveobjects.assertWaiter -import io.ably.lib.liveobjects.unit.getMockAblyClientAdapter -import io.ably.lib.liveobjects.value.livecounter.InternalLiveCounter -import io.ably.lib.liveobjects.value.livemap.InternalLiveMap -import io.ably.lib.realtime.ChannelState +package io.ably.pubsub.liveobjects.uts.unit + +import io.ably.pubsub.liveobjects.DefaultRealtimeObject +import io.ably.pubsub.liveobjects.ObjectsState +import io.ably.pubsub.liveobjects.ROOT_OBJECT_ID +import io.ably.pubsub.liveobjects.assertWaiter +import io.ably.pubsub.liveobjects.unit.getMockAblyClientAdapter +import io.ably.pubsub.liveobjects.value.livecounter.InternalLiveCounter +import io.ably.pubsub.liveobjects.value.livemap.InternalLiveMap +import io.ably.pubsub.realtime.ChannelState import io.mockk.unmockkAll import kotlinx.coroutines.test.runTest import kotlin.test.AfterTest diff --git a/liveobjects/src/test/kotlin/io/ably/lib/liveobjects/uts/unit/PathObjectMutationsTest.kt b/liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/uts/unit/PathObjectMutationsTest.kt similarity index 97% rename from liveobjects/src/test/kotlin/io/ably/lib/liveobjects/uts/unit/PathObjectMutationsTest.kt rename to liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/uts/unit/PathObjectMutationsTest.kt index c6497481f..bb6c61a36 100644 --- a/liveobjects/src/test/kotlin/io/ably/lib/liveobjects/uts/unit/PathObjectMutationsTest.kt +++ b/liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/uts/unit/PathObjectMutationsTest.kt @@ -1,7 +1,7 @@ -package io.ably.lib.liveobjects.uts.unit +package io.ably.pubsub.liveobjects.uts.unit -import io.ably.lib.liveobjects.value.LiveMapValue -import io.ably.lib.types.AblyException +import io.ably.pubsub.liveobjects.value.LiveMapValue +import io.ably.pubsub.types.AblyException import kotlinx.coroutines.future.await import kotlinx.coroutines.test.runTest import kotlin.test.Test diff --git a/liveobjects/src/test/kotlin/io/ably/lib/liveobjects/uts/unit/PathObjectSubscribeTest.kt b/liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/uts/unit/PathObjectSubscribeTest.kt similarity index 97% rename from liveobjects/src/test/kotlin/io/ably/lib/liveobjects/uts/unit/PathObjectSubscribeTest.kt rename to liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/uts/unit/PathObjectSubscribeTest.kt index e641eb5e6..a565f1e13 100644 --- a/liveobjects/src/test/kotlin/io/ably/lib/liveobjects/uts/unit/PathObjectSubscribeTest.kt +++ b/liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/uts/unit/PathObjectSubscribeTest.kt @@ -1,21 +1,21 @@ -package io.ably.lib.liveobjects.uts.unit - -import io.ably.lib.liveobjects.Subscription -import io.ably.lib.liveobjects.message.ObjectOperationAction -import io.ably.lib.liveobjects.path.PathObject -import io.ably.lib.liveobjects.path.PathObjectListener -import io.ably.lib.liveobjects.path.PathObjectSubscriptionEvent -import io.ably.lib.liveobjects.path.PathObjectSubscriptionOptions -import io.ably.lib.realtime.ChannelState -import io.ably.lib.types.AblyException -import io.ably.lib.types.ChannelMode -import io.ably.lib.types.ChannelOptions -import io.ably.lib.types.ProtocolMessage -import io.ably.lib.uts.infra.awaitChannelState -import io.ably.lib.uts.infra.pollUntil -import io.ably.lib.uts.infra.unit.ConnectionDetails -import io.ably.lib.uts.infra.unit.MockWebSocket -import io.ably.lib.uts.infra.unit.TestRealtimeClient +package io.ably.pubsub.liveobjects.uts.unit + +import io.ably.pubsub.liveobjects.Subscription +import io.ably.pubsub.liveobjects.message.ObjectOperationAction +import io.ably.pubsub.liveobjects.path.PathObject +import io.ably.pubsub.liveobjects.path.PathObjectListener +import io.ably.pubsub.liveobjects.path.PathObjectSubscriptionEvent +import io.ably.pubsub.liveobjects.path.PathObjectSubscriptionOptions +import io.ably.pubsub.realtime.ChannelState +import io.ably.pubsub.types.AblyException +import io.ably.pubsub.types.ChannelMode +import io.ably.pubsub.types.ChannelOptions +import io.ably.pubsub.types.ProtocolMessage +import io.ably.pubsub.uts.infra.awaitChannelState +import io.ably.pubsub.uts.infra.pollUntil +import io.ably.pubsub.uts.infra.unit.ConnectionDetails +import io.ably.pubsub.uts.infra.unit.MockWebSocket +import io.ably.pubsub.uts.infra.unit.TestRealtimeClient import kotlinx.coroutines.future.await import kotlinx.coroutines.test.runTest import kotlin.test.Test diff --git a/liveobjects/src/test/kotlin/io/ably/lib/liveobjects/uts/unit/PathObjectTest.kt b/liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/uts/unit/PathObjectTest.kt similarity index 98% rename from liveobjects/src/test/kotlin/io/ably/lib/liveobjects/uts/unit/PathObjectTest.kt rename to liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/uts/unit/PathObjectTest.kt index 63ade05b0..db00c4ee1 100644 --- a/liveobjects/src/test/kotlin/io/ably/lib/liveobjects/uts/unit/PathObjectTest.kt +++ b/liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/uts/unit/PathObjectTest.kt @@ -1,9 +1,9 @@ -package io.ably.lib.liveobjects.uts.unit +package io.ably.pubsub.liveobjects.uts.unit import com.google.gson.JsonParser -import io.ably.lib.liveobjects.ValueType -import io.ably.lib.liveobjects.instance.Instance -import io.ably.lib.uts.infra.pollUntil +import io.ably.pubsub.liveobjects.ValueType +import io.ably.pubsub.liveobjects.instance.Instance +import io.ably.pubsub.uts.infra.pollUntil import kotlinx.coroutines.test.runTest import kotlin.test.Test import kotlin.test.assertContains diff --git a/liveobjects/src/test/kotlin/io/ably/lib/liveobjects/uts/unit/PublicObjectMessageTest.kt b/liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/uts/unit/PublicObjectMessageTest.kt similarity index 92% rename from liveobjects/src/test/kotlin/io/ably/lib/liveobjects/uts/unit/PublicObjectMessageTest.kt rename to liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/uts/unit/PublicObjectMessageTest.kt index ec8922a53..8f483828d 100644 --- a/liveobjects/src/test/kotlin/io/ably/lib/liveobjects/uts/unit/PublicObjectMessageTest.kt +++ b/liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/uts/unit/PublicObjectMessageTest.kt @@ -1,24 +1,24 @@ -package io.ably.lib.liveobjects.uts.unit +package io.ably.pubsub.liveobjects.uts.unit import com.google.gson.JsonObject -import io.ably.lib.liveobjects.message.ObjectOperation -import io.ably.lib.liveobjects.message.ObjectOperationAction -import io.ably.lib.liveobjects.message.ObjectsMapSemantics -import io.ably.lib.liveobjects.message.WireCounterCreate -import io.ably.lib.liveobjects.message.WireCounterCreateWithObjectId -import io.ably.lib.liveobjects.message.WireCounterInc -import io.ably.lib.liveobjects.message.WireMapClear -import io.ably.lib.liveobjects.message.WireMapCreate -import io.ably.lib.liveobjects.message.WireMapCreateWithObjectId -import io.ably.lib.liveobjects.message.WireMapRemove -import io.ably.lib.liveobjects.message.WireMapSet -import io.ably.lib.liveobjects.message.WireObjectData -import io.ably.lib.liveobjects.message.WireObjectDelete -import io.ably.lib.liveobjects.message.WireObjectMessage -import io.ably.lib.liveobjects.message.WireObjectOperation -import io.ably.lib.liveobjects.message.WireObjectOperationAction -import io.ably.lib.liveobjects.message.WireObjectsMapEntry -import io.ably.lib.liveobjects.message.WireObjectsMapSemantics +import io.ably.pubsub.liveobjects.message.ObjectOperation +import io.ably.pubsub.liveobjects.message.ObjectOperationAction +import io.ably.pubsub.liveobjects.message.ObjectsMapSemantics +import io.ably.pubsub.liveobjects.message.WireCounterCreate +import io.ably.pubsub.liveobjects.message.WireCounterCreateWithObjectId +import io.ably.pubsub.liveobjects.message.WireCounterInc +import io.ably.pubsub.liveobjects.message.WireMapClear +import io.ably.pubsub.liveobjects.message.WireMapCreate +import io.ably.pubsub.liveobjects.message.WireMapCreateWithObjectId +import io.ably.pubsub.liveobjects.message.WireMapRemove +import io.ably.pubsub.liveobjects.message.WireMapSet +import io.ably.pubsub.liveobjects.message.WireObjectData +import io.ably.pubsub.liveobjects.message.WireObjectDelete +import io.ably.pubsub.liveobjects.message.WireObjectMessage +import io.ably.pubsub.liveobjects.message.WireObjectOperation +import io.ably.pubsub.liveobjects.message.WireObjectOperationAction +import io.ably.pubsub.liveobjects.message.WireObjectsMapEntry +import io.ably.pubsub.liveobjects.message.WireObjectsMapSemantics import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertNotNull diff --git a/liveobjects/src/test/kotlin/io/ably/lib/liveobjects/uts/unit/RealtimeObjectTest.kt b/liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/uts/unit/RealtimeObjectTest.kt similarity index 96% rename from liveobjects/src/test/kotlin/io/ably/lib/liveobjects/uts/unit/RealtimeObjectTest.kt rename to liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/uts/unit/RealtimeObjectTest.kt index e45d09b7f..b94961968 100644 --- a/liveobjects/src/test/kotlin/io/ably/lib/liveobjects/uts/unit/RealtimeObjectTest.kt +++ b/liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/uts/unit/RealtimeObjectTest.kt @@ -1,36 +1,35 @@ -package io.ably.lib.liveobjects.uts.unit - -import io.ably.lib.liveobjects.DefaultRealtimeObject -import io.ably.lib.liveobjects.ROOT_OBJECT_ID -import io.ably.lib.liveobjects.instance.InstanceListener -import io.ably.lib.liveobjects.message.WireObjectMessage -import io.ably.lib.liveobjects.message.WireObjectOperationAction -import io.ably.lib.liveobjects.path.PathObject -import io.ably.lib.liveobjects.path.PathObjectListener -import io.ably.lib.liveobjects.path.PathObjectSubscriptionEvent -import io.ably.lib.liveobjects.path.PathObjectSubscriptionOptions -import io.ably.lib.liveobjects.path.types.LiveMapPathObject -import io.ably.lib.liveobjects.state.ObjectStateChange -import io.ably.lib.liveobjects.state.ObjectStateEvent -import io.ably.lib.liveobjects.value.LiveMapValue -import io.ably.lib.liveobjects.value.livecounter.InternalLiveCounter -import io.ably.lib.liveobjects.value.livemap.InternalLiveMap -import io.ably.lib.realtime.AblyRealtime -import io.ably.lib.realtime.Channel -import io.ably.lib.realtime.ChannelState -import io.ably.lib.types.AblyException -import io.ably.lib.types.ChannelMode -import io.ably.lib.types.ChannelOptions -import io.ably.lib.types.ErrorInfo -import io.ably.lib.types.ProtocolMessage -import io.ably.lib.types.PublishResult -import io.ably.lib.uts.infra.awaitChannelState -import io.ably.lib.uts.infra.pollUntil -import io.ably.lib.uts.infra.unit.ConnectionDetails -import io.ably.lib.uts.infra.unit.FakeClock -import io.ably.lib.uts.infra.unit.MockEvent -import io.ably.lib.uts.infra.unit.MockWebSocket -import io.ably.lib.uts.infra.unit.TestRealtimeClient +package io.ably.pubsub.liveobjects.uts.unit + +import io.ably.pubsub.liveobjects.DefaultRealtimeObject +import io.ably.pubsub.liveobjects.ROOT_OBJECT_ID +import io.ably.pubsub.liveobjects.instance.InstanceListener +import io.ably.pubsub.liveobjects.message.WireObjectMessage +import io.ably.pubsub.liveobjects.message.WireObjectOperationAction +import io.ably.pubsub.liveobjects.path.PathObject +import io.ably.pubsub.liveobjects.path.PathObjectListener +import io.ably.pubsub.liveobjects.path.PathObjectSubscriptionEvent +import io.ably.pubsub.liveobjects.path.PathObjectSubscriptionOptions +import io.ably.pubsub.liveobjects.path.types.LiveMapPathObject +import io.ably.pubsub.liveobjects.state.ObjectStateChange +import io.ably.pubsub.liveobjects.state.ObjectStateEvent +import io.ably.pubsub.liveobjects.value.LiveMapValue +import io.ably.pubsub.liveobjects.value.livecounter.InternalLiveCounter +import io.ably.pubsub.liveobjects.value.livemap.InternalLiveMap +import io.ably.pubsub.realtime.PubSubRealtimeClient +import io.ably.pubsub.realtime.Channel +import io.ably.pubsub.realtime.ChannelState +import io.ably.pubsub.types.AblyException +import io.ably.pubsub.types.ChannelMode +import io.ably.pubsub.types.ChannelOptions +import io.ably.pubsub.types.ErrorInfo +import io.ably.pubsub.types.ProtocolMessage +import io.ably.pubsub.types.PublishResult +import io.ably.pubsub.uts.infra.awaitChannelState +import io.ably.pubsub.uts.infra.pollUntil +import io.ably.pubsub.uts.infra.unit.ConnectionDetails +import io.ably.pubsub.uts.infra.unit.FakeClock +import io.ably.pubsub.uts.infra.unit.MockWebSocket +import io.ably.pubsub.uts.infra.unit.TestRealtimeClient import kotlinx.coroutines.future.await import kotlinx.coroutines.test.runTest import java.util.concurrent.CopyOnWriteArrayList @@ -142,14 +141,14 @@ class RealtimeObjectTest { mockWs: MockWebSocket, echo: Boolean = true, fakeClock: FakeClock? = null, - ): AblyRealtime = TestRealtimeClient { + ): PubSubRealtimeClient = TestRealtimeClient { key = "fake:key" echoMessages = echo install(mockWs) fakeClock?.let { enableFakeTimers(it) } } - private fun AblyRealtime.objectsChannel( + private fun PubSubRealtimeClient.objectsChannel( name: String, modes: Array = arrayOf(ChannelMode.object_subscribe, ChannelMode.object_publish), ): Channel = channels.get(name, ChannelOptions().apply { this.modes = modes }) @@ -179,7 +178,7 @@ class RealtimeObjectTest { /** The fake-timers variant of the spec's `{ client, channel, root, mock_ws }` tuple. */ private data class FakeTimersChannel( - val client: AblyRealtime, + val client: PubSubRealtimeClient, val channel: Channel, val root: LiveMapPathObject, val mockWs: MockWebSocket, diff --git a/liveobjects/src/test/kotlin/io/ably/lib/liveobjects/uts/unit/ValueTypesTest.kt b/liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/uts/unit/ValueTypesTest.kt similarity index 94% rename from liveobjects/src/test/kotlin/io/ably/lib/liveobjects/uts/unit/ValueTypesTest.kt rename to liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/uts/unit/ValueTypesTest.kt index 8a8d528e1..30cf99d56 100644 --- a/liveobjects/src/test/kotlin/io/ably/lib/liveobjects/uts/unit/ValueTypesTest.kt +++ b/liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/uts/unit/ValueTypesTest.kt @@ -1,19 +1,19 @@ -package io.ably.lib.liveobjects.uts.unit +package io.ably.pubsub.liveobjects.uts.unit import com.google.gson.JsonParser -import io.ably.lib.liveobjects.DefaultRealtimeObject -import io.ably.lib.liveobjects.message.WireMapCreate -import io.ably.lib.liveobjects.message.WireObjectData -import io.ably.lib.liveobjects.message.WireObjectMessage -import io.ably.lib.liveobjects.message.WireObjectOperationAction -import io.ably.lib.liveobjects.message.WireObjectsMapSemantics -import io.ably.lib.liveobjects.unit.getMockAblyClientAdapter -import io.ably.lib.liveobjects.value.LiveCounter -import io.ably.lib.liveobjects.value.LiveMap -import io.ably.lib.liveobjects.value.LiveMapValue -import io.ably.lib.liveobjects.value.livecounter.DefaultLiveCounter -import io.ably.lib.liveobjects.value.livemap.DefaultLiveMap -import io.ably.lib.types.AblyException +import io.ably.pubsub.liveobjects.DefaultRealtimeObject +import io.ably.pubsub.liveobjects.message.WireMapCreate +import io.ably.pubsub.liveobjects.message.WireObjectData +import io.ably.pubsub.liveobjects.message.WireObjectMessage +import io.ably.pubsub.liveobjects.message.WireObjectOperationAction +import io.ably.pubsub.liveobjects.message.WireObjectsMapSemantics +import io.ably.pubsub.liveobjects.unit.getMockAblyClientAdapter +import io.ably.pubsub.liveobjects.value.LiveCounter +import io.ably.pubsub.liveobjects.value.LiveMap +import io.ably.pubsub.liveobjects.value.LiveMapValue +import io.ably.pubsub.liveobjects.value.livecounter.DefaultLiveCounter +import io.ably.pubsub.liveobjects.value.livemap.DefaultLiveMap +import io.ably.pubsub.types.AblyException import io.mockk.unmockkAll import kotlinx.coroutines.test.runTest import kotlin.test.AfterTest diff --git a/network-client-core/src/main/java/io/ably/lib/network/EngineType.java b/network-client-core/src/main/java/io/ably/pubsub/network/EngineType.java similarity index 61% rename from network-client-core/src/main/java/io/ably/lib/network/EngineType.java rename to network-client-core/src/main/java/io/ably/pubsub/network/EngineType.java index d3984de23..e62698c9d 100644 --- a/network-client-core/src/main/java/io/ably/lib/network/EngineType.java +++ b/network-client-core/src/main/java/io/ably/pubsub/network/EngineType.java @@ -1,4 +1,4 @@ -package io.ably.lib.network; +package io.ably.pubsub.network; public enum EngineType { DEFAULT, diff --git a/network-client-core/src/main/java/io/ably/lib/network/FailedConnectionException.java b/network-client-core/src/main/java/io/ably/pubsub/network/FailedConnectionException.java similarity index 82% rename from network-client-core/src/main/java/io/ably/lib/network/FailedConnectionException.java rename to network-client-core/src/main/java/io/ably/pubsub/network/FailedConnectionException.java index cc226716a..7cea40632 100644 --- a/network-client-core/src/main/java/io/ably/lib/network/FailedConnectionException.java +++ b/network-client-core/src/main/java/io/ably/pubsub/network/FailedConnectionException.java @@ -1,4 +1,4 @@ -package io.ably.lib.network; +package io.ably.pubsub.network; public class FailedConnectionException extends RuntimeException { public FailedConnectionException(Throwable cause) { diff --git a/network-client-core/src/main/java/io/ably/lib/network/HttpBody.java b/network-client-core/src/main/java/io/ably/pubsub/network/HttpBody.java similarity index 88% rename from network-client-core/src/main/java/io/ably/lib/network/HttpBody.java rename to network-client-core/src/main/java/io/ably/pubsub/network/HttpBody.java index 00102dbc5..814682c6c 100644 --- a/network-client-core/src/main/java/io/ably/lib/network/HttpBody.java +++ b/network-client-core/src/main/java/io/ably/pubsub/network/HttpBody.java @@ -1,4 +1,4 @@ -package io.ably.lib.network; +package io.ably.pubsub.network; import lombok.AccessLevel; import lombok.AllArgsConstructor; diff --git a/network-client-core/src/main/java/io/ably/lib/network/HttpCall.java b/network-client-core/src/main/java/io/ably/pubsub/network/HttpCall.java similarity index 90% rename from network-client-core/src/main/java/io/ably/lib/network/HttpCall.java rename to network-client-core/src/main/java/io/ably/pubsub/network/HttpCall.java index 87e77aa40..13bbcec66 100644 --- a/network-client-core/src/main/java/io/ably/lib/network/HttpCall.java +++ b/network-client-core/src/main/java/io/ably/pubsub/network/HttpCall.java @@ -1,4 +1,4 @@ -package io.ably.lib.network; +package io.ably.pubsub.network; /** * Cancelable Http request call diff --git a/network-client-core/src/main/java/io/ably/lib/network/HttpEngine.java b/network-client-core/src/main/java/io/ably/pubsub/network/HttpEngine.java similarity index 93% rename from network-client-core/src/main/java/io/ably/lib/network/HttpEngine.java rename to network-client-core/src/main/java/io/ably/pubsub/network/HttpEngine.java index eae17fd4a..386e9d730 100644 --- a/network-client-core/src/main/java/io/ably/lib/network/HttpEngine.java +++ b/network-client-core/src/main/java/io/ably/pubsub/network/HttpEngine.java @@ -1,4 +1,4 @@ -package io.ably.lib.network; +package io.ably.pubsub.network; /** * An HTTP engine instance that can make cancelable HTTP requests. diff --git a/network-client-core/src/main/java/io/ably/lib/network/HttpEngineConfig.java b/network-client-core/src/main/java/io/ably/pubsub/network/HttpEngineConfig.java similarity index 89% rename from network-client-core/src/main/java/io/ably/lib/network/HttpEngineConfig.java rename to network-client-core/src/main/java/io/ably/pubsub/network/HttpEngineConfig.java index e19c63029..2dd7860da 100644 --- a/network-client-core/src/main/java/io/ably/lib/network/HttpEngineConfig.java +++ b/network-client-core/src/main/java/io/ably/pubsub/network/HttpEngineConfig.java @@ -1,4 +1,4 @@ -package io.ably.lib.network; +package io.ably.pubsub.network; import lombok.AccessLevel; import lombok.AllArgsConstructor; diff --git a/network-client-core/src/main/java/io/ably/lib/network/HttpEngineFactory.java b/network-client-core/src/main/java/io/ably/pubsub/network/HttpEngineFactory.java similarity index 93% rename from network-client-core/src/main/java/io/ably/lib/network/HttpEngineFactory.java rename to network-client-core/src/main/java/io/ably/pubsub/network/HttpEngineFactory.java index e388064a0..83b62b0bb 100644 --- a/network-client-core/src/main/java/io/ably/lib/network/HttpEngineFactory.java +++ b/network-client-core/src/main/java/io/ably/pubsub/network/HttpEngineFactory.java @@ -1,4 +1,4 @@ -package io.ably.lib.network; +package io.ably.pubsub.network; import java.lang.reflect.InvocationTargetException; @@ -20,7 +20,7 @@ static HttpEngineFactory getFirstAvailable() { static HttpEngineFactory tryGetOkHttpFactory() { try { - Class okHttpFactoryClass = Class.forName("io.ably.lib.network.OkHttpEngineFactory"); + Class okHttpFactoryClass = Class.forName("io.ably.pubsub.network.OkHttpEngineFactory"); return (HttpEngineFactory) okHttpFactoryClass.getDeclaredConstructor().newInstance(); } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | NoSuchMethodException | InvocationTargetException e) { @@ -30,7 +30,7 @@ static HttpEngineFactory tryGetOkHttpFactory() { static HttpEngineFactory tryGetDefaultFactory() { try { - Class defaultFactoryClass = Class.forName("io.ably.lib.network.DefaultHttpEngineFactory"); + Class defaultFactoryClass = Class.forName("io.ably.pubsub.network.DefaultHttpEngineFactory"); return (HttpEngineFactory) defaultFactoryClass.getDeclaredConstructor().newInstance(); } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | NoSuchMethodException | InvocationTargetException e) { diff --git a/network-client-core/src/main/java/io/ably/lib/network/HttpRequest.java b/network-client-core/src/main/java/io/ably/pubsub/network/HttpRequest.java similarity index 99% rename from network-client-core/src/main/java/io/ably/lib/network/HttpRequest.java rename to network-client-core/src/main/java/io/ably/pubsub/network/HttpRequest.java index 361506ccb..587d04c96 100644 --- a/network-client-core/src/main/java/io/ably/lib/network/HttpRequest.java +++ b/network-client-core/src/main/java/io/ably/pubsub/network/HttpRequest.java @@ -1,4 +1,4 @@ -package io.ably.lib.network; +package io.ably.pubsub.network; import lombok.AccessLevel; import lombok.AllArgsConstructor; diff --git a/network-client-core/src/main/java/io/ably/lib/network/HttpResponse.java b/network-client-core/src/main/java/io/ably/pubsub/network/HttpResponse.java similarity index 92% rename from network-client-core/src/main/java/io/ably/lib/network/HttpResponse.java rename to network-client-core/src/main/java/io/ably/pubsub/network/HttpResponse.java index e2cf4103c..a159acf8d 100644 --- a/network-client-core/src/main/java/io/ably/lib/network/HttpResponse.java +++ b/network-client-core/src/main/java/io/ably/pubsub/network/HttpResponse.java @@ -1,4 +1,4 @@ -package io.ably.lib.network; +package io.ably.pubsub.network; import lombok.AccessLevel; import lombok.AllArgsConstructor; diff --git a/network-client-core/src/main/java/io/ably/lib/network/NotConnectedException.java b/network-client-core/src/main/java/io/ably/pubsub/network/NotConnectedException.java similarity index 81% rename from network-client-core/src/main/java/io/ably/lib/network/NotConnectedException.java rename to network-client-core/src/main/java/io/ably/pubsub/network/NotConnectedException.java index 166549e81..2523a9245 100644 --- a/network-client-core/src/main/java/io/ably/lib/network/NotConnectedException.java +++ b/network-client-core/src/main/java/io/ably/pubsub/network/NotConnectedException.java @@ -1,4 +1,4 @@ -package io.ably.lib.network; +package io.ably.pubsub.network; public class NotConnectedException extends RuntimeException { public NotConnectedException(Throwable cause) { diff --git a/network-client-core/src/main/java/io/ably/lib/network/ProxyAuthType.java b/network-client-core/src/main/java/io/ably/pubsub/network/ProxyAuthType.java similarity index 62% rename from network-client-core/src/main/java/io/ably/lib/network/ProxyAuthType.java rename to network-client-core/src/main/java/io/ably/pubsub/network/ProxyAuthType.java index ca4cb57a5..50033ae69 100644 --- a/network-client-core/src/main/java/io/ably/lib/network/ProxyAuthType.java +++ b/network-client-core/src/main/java/io/ably/pubsub/network/ProxyAuthType.java @@ -1,4 +1,4 @@ -package io.ably.lib.network; +package io.ably.pubsub.network; public enum ProxyAuthType { BASIC, diff --git a/network-client-core/src/main/java/io/ably/lib/network/ProxyConfig.java b/network-client-core/src/main/java/io/ably/pubsub/network/ProxyConfig.java similarity index 92% rename from network-client-core/src/main/java/io/ably/lib/network/ProxyConfig.java rename to network-client-core/src/main/java/io/ably/pubsub/network/ProxyConfig.java index 8b87a6846..e72b4463c 100644 --- a/network-client-core/src/main/java/io/ably/lib/network/ProxyConfig.java +++ b/network-client-core/src/main/java/io/ably/pubsub/network/ProxyConfig.java @@ -1,4 +1,4 @@ -package io.ably.lib.network; +package io.ably.pubsub.network; import lombok.AccessLevel; import lombok.AllArgsConstructor; diff --git a/network-client-core/src/main/java/io/ably/lib/network/WebSocketClient.java b/network-client-core/src/main/java/io/ably/pubsub/network/WebSocketClient.java similarity index 97% rename from network-client-core/src/main/java/io/ably/lib/network/WebSocketClient.java rename to network-client-core/src/main/java/io/ably/pubsub/network/WebSocketClient.java index 9452fc132..1cbb01316 100644 --- a/network-client-core/src/main/java/io/ably/lib/network/WebSocketClient.java +++ b/network-client-core/src/main/java/io/ably/pubsub/network/WebSocketClient.java @@ -1,4 +1,4 @@ -package io.ably.lib.network; +package io.ably.pubsub.network; /** * WebSocketClient instance bind to the specified URI. diff --git a/network-client-core/src/main/java/io/ably/lib/network/WebSocketEngine.java b/network-client-core/src/main/java/io/ably/pubsub/network/WebSocketEngine.java similarity index 86% rename from network-client-core/src/main/java/io/ably/lib/network/WebSocketEngine.java rename to network-client-core/src/main/java/io/ably/pubsub/network/WebSocketEngine.java index af29dce14..95d254c23 100644 --- a/network-client-core/src/main/java/io/ably/lib/network/WebSocketEngine.java +++ b/network-client-core/src/main/java/io/ably/pubsub/network/WebSocketEngine.java @@ -1,4 +1,4 @@ -package io.ably.lib.network; +package io.ably.pubsub.network; /** * Create WebSocket client bind to the specific URL diff --git a/network-client-core/src/main/java/io/ably/lib/network/WebSocketEngineConfig.java b/network-client-core/src/main/java/io/ably/pubsub/network/WebSocketEngineConfig.java similarity index 92% rename from network-client-core/src/main/java/io/ably/lib/network/WebSocketEngineConfig.java rename to network-client-core/src/main/java/io/ably/pubsub/network/WebSocketEngineConfig.java index b294c58c0..87008e138 100644 --- a/network-client-core/src/main/java/io/ably/lib/network/WebSocketEngineConfig.java +++ b/network-client-core/src/main/java/io/ably/pubsub/network/WebSocketEngineConfig.java @@ -1,4 +1,4 @@ -package io.ably.lib.network; +package io.ably.pubsub.network; import lombok.AccessLevel; import lombok.AllArgsConstructor; diff --git a/network-client-core/src/main/java/io/ably/lib/network/WebSocketEngineFactory.java b/network-client-core/src/main/java/io/ably/pubsub/network/WebSocketEngineFactory.java similarity index 92% rename from network-client-core/src/main/java/io/ably/lib/network/WebSocketEngineFactory.java rename to network-client-core/src/main/java/io/ably/pubsub/network/WebSocketEngineFactory.java index c5693d655..267e5574d 100644 --- a/network-client-core/src/main/java/io/ably/lib/network/WebSocketEngineFactory.java +++ b/network-client-core/src/main/java/io/ably/pubsub/network/WebSocketEngineFactory.java @@ -1,4 +1,4 @@ -package io.ably.lib.network; +package io.ably.pubsub.network; import java.lang.reflect.InvocationTargetException; @@ -19,7 +19,7 @@ static WebSocketEngineFactory getFirstAvailable() { static WebSocketEngineFactory tryGetOkWebSocketFactory() { try { - Class okWebSocketFactoryClass = Class.forName("io.ably.lib.network.OkHttpWebSocketEngineFactory"); + Class okWebSocketFactoryClass = Class.forName("io.ably.pubsub.network.OkHttpWebSocketEngineFactory"); return (WebSocketEngineFactory) okWebSocketFactoryClass.getDeclaredConstructor().newInstance(); } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | NoSuchMethodException | InvocationTargetException e) { @@ -29,7 +29,7 @@ static WebSocketEngineFactory tryGetOkWebSocketFactory() { static WebSocketEngineFactory tryGetDefaultFactory() { try { - Class defaultFactoryClass = Class.forName("io.ably.lib.network.DefaultWebSocketEngineFactory"); + Class defaultFactoryClass = Class.forName("io.ably.pubsub.network.DefaultWebSocketEngineFactory"); return (WebSocketEngineFactory) defaultFactoryClass.getDeclaredConstructor().newInstance(); } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | NoSuchMethodException | InvocationTargetException e) { diff --git a/network-client-core/src/main/java/io/ably/lib/network/WebSocketListener.java b/network-client-core/src/main/java/io/ably/pubsub/network/WebSocketListener.java similarity index 98% rename from network-client-core/src/main/java/io/ably/lib/network/WebSocketListener.java rename to network-client-core/src/main/java/io/ably/pubsub/network/WebSocketListener.java index 003d2a7bf..fccaf9079 100644 --- a/network-client-core/src/main/java/io/ably/lib/network/WebSocketListener.java +++ b/network-client-core/src/main/java/io/ably/pubsub/network/WebSocketListener.java @@ -1,4 +1,4 @@ -package io.ably.lib.network; +package io.ably.pubsub.network; import java.nio.ByteBuffer; diff --git a/network-client-default/src/main/java/io/ably/lib/network/DefaultHttpCall.java b/network-client-default/src/main/java/io/ably/pubsub/network/DefaultHttpCall.java similarity index 99% rename from network-client-default/src/main/java/io/ably/lib/network/DefaultHttpCall.java rename to network-client-default/src/main/java/io/ably/pubsub/network/DefaultHttpCall.java index bfc3a78d0..eaa278558 100644 --- a/network-client-default/src/main/java/io/ably/lib/network/DefaultHttpCall.java +++ b/network-client-default/src/main/java/io/ably/pubsub/network/DefaultHttpCall.java @@ -1,4 +1,4 @@ -package io.ably.lib.network; +package io.ably.pubsub.network; import java.io.ByteArrayOutputStream; import java.io.IOException; diff --git a/network-client-default/src/main/java/io/ably/lib/network/DefaultHttpEngine.java b/network-client-default/src/main/java/io/ably/pubsub/network/DefaultHttpEngine.java similarity index 95% rename from network-client-default/src/main/java/io/ably/lib/network/DefaultHttpEngine.java rename to network-client-default/src/main/java/io/ably/pubsub/network/DefaultHttpEngine.java index e61b58d95..5d569dac8 100644 --- a/network-client-default/src/main/java/io/ably/lib/network/DefaultHttpEngine.java +++ b/network-client-default/src/main/java/io/ably/pubsub/network/DefaultHttpEngine.java @@ -1,4 +1,4 @@ -package io.ably.lib.network; +package io.ably.pubsub.network; import java.net.InetSocketAddress; import java.net.Proxy; diff --git a/network-client-default/src/main/java/io/ably/lib/network/DefaultHttpEngineFactory.java b/network-client-default/src/main/java/io/ably/pubsub/network/DefaultHttpEngineFactory.java similarity index 90% rename from network-client-default/src/main/java/io/ably/lib/network/DefaultHttpEngineFactory.java rename to network-client-default/src/main/java/io/ably/pubsub/network/DefaultHttpEngineFactory.java index 533f06d91..4af64a1bf 100644 --- a/network-client-default/src/main/java/io/ably/lib/network/DefaultHttpEngineFactory.java +++ b/network-client-default/src/main/java/io/ably/pubsub/network/DefaultHttpEngineFactory.java @@ -1,4 +1,4 @@ -package io.ably.lib.network; +package io.ably.pubsub.network; public class DefaultHttpEngineFactory implements HttpEngineFactory { diff --git a/network-client-default/src/main/java/io/ably/lib/network/DefaultWebSocketClient.java b/network-client-default/src/main/java/io/ably/pubsub/network/DefaultWebSocketClient.java similarity index 99% rename from network-client-default/src/main/java/io/ably/lib/network/DefaultWebSocketClient.java rename to network-client-default/src/main/java/io/ably/pubsub/network/DefaultWebSocketClient.java index 3cd4b068e..a08bbd26f 100644 --- a/network-client-default/src/main/java/io/ably/lib/network/DefaultWebSocketClient.java +++ b/network-client-default/src/main/java/io/ably/pubsub/network/DefaultWebSocketClient.java @@ -1,4 +1,4 @@ -package io.ably.lib.network; +package io.ably.pubsub.network; import org.java_websocket.WebSocket; import org.java_websocket.exceptions.WebsocketNotConnectedException; diff --git a/network-client-default/src/main/java/io/ably/lib/network/DefaultWebSocketEngine.java b/network-client-default/src/main/java/io/ably/pubsub/network/DefaultWebSocketEngine.java similarity index 95% rename from network-client-default/src/main/java/io/ably/lib/network/DefaultWebSocketEngine.java rename to network-client-default/src/main/java/io/ably/pubsub/network/DefaultWebSocketEngine.java index a73f9f580..c608ddab0 100644 --- a/network-client-default/src/main/java/io/ably/lib/network/DefaultWebSocketEngine.java +++ b/network-client-default/src/main/java/io/ably/pubsub/network/DefaultWebSocketEngine.java @@ -1,4 +1,4 @@ -package io.ably.lib.network; +package io.ably.pubsub.network; import java.net.URI; diff --git a/network-client-default/src/main/java/io/ably/lib/network/DefaultWebSocketEngineFactory.java b/network-client-default/src/main/java/io/ably/pubsub/network/DefaultWebSocketEngineFactory.java similarity index 90% rename from network-client-default/src/main/java/io/ably/lib/network/DefaultWebSocketEngineFactory.java rename to network-client-default/src/main/java/io/ably/pubsub/network/DefaultWebSocketEngineFactory.java index 48b564e2c..904a7a698 100644 --- a/network-client-default/src/main/java/io/ably/lib/network/DefaultWebSocketEngineFactory.java +++ b/network-client-default/src/main/java/io/ably/pubsub/network/DefaultWebSocketEngineFactory.java @@ -1,4 +1,4 @@ -package io.ably.lib.network; +package io.ably.pubsub.network; public class DefaultWebSocketEngineFactory implements WebSocketEngineFactory { diff --git a/network-client-okhttp/src/main/java/io/ably/lib/network/OkHttpCall.java b/network-client-okhttp/src/main/java/io/ably/pubsub/network/OkHttpCall.java similarity index 97% rename from network-client-okhttp/src/main/java/io/ably/lib/network/OkHttpCall.java rename to network-client-okhttp/src/main/java/io/ably/pubsub/network/OkHttpCall.java index c366fd7b8..93678dac8 100644 --- a/network-client-okhttp/src/main/java/io/ably/lib/network/OkHttpCall.java +++ b/network-client-okhttp/src/main/java/io/ably/pubsub/network/OkHttpCall.java @@ -1,4 +1,4 @@ -package io.ably.lib.network; +package io.ably.pubsub.network; import okhttp3.Call; import okhttp3.MediaType; diff --git a/network-client-okhttp/src/main/java/io/ably/lib/network/OkHttpEngine.java b/network-client-okhttp/src/main/java/io/ably/pubsub/network/OkHttpEngine.java similarity index 96% rename from network-client-okhttp/src/main/java/io/ably/lib/network/OkHttpEngine.java rename to network-client-okhttp/src/main/java/io/ably/pubsub/network/OkHttpEngine.java index 50faa3610..83a40a181 100644 --- a/network-client-okhttp/src/main/java/io/ably/lib/network/OkHttpEngine.java +++ b/network-client-okhttp/src/main/java/io/ably/pubsub/network/OkHttpEngine.java @@ -1,4 +1,4 @@ -package io.ably.lib.network; +package io.ably.pubsub.network; import okhttp3.Call; import okhttp3.OkHttpClient; diff --git a/network-client-okhttp/src/main/java/io/ably/lib/network/OkHttpEngineFactory.java b/network-client-okhttp/src/main/java/io/ably/pubsub/network/OkHttpEngineFactory.java similarity index 93% rename from network-client-okhttp/src/main/java/io/ably/lib/network/OkHttpEngineFactory.java rename to network-client-okhttp/src/main/java/io/ably/pubsub/network/OkHttpEngineFactory.java index 2cf65a9a8..15cd08eea 100644 --- a/network-client-okhttp/src/main/java/io/ably/lib/network/OkHttpEngineFactory.java +++ b/network-client-okhttp/src/main/java/io/ably/pubsub/network/OkHttpEngineFactory.java @@ -1,4 +1,4 @@ -package io.ably.lib.network; +package io.ably.pubsub.network; import okhttp3.OkHttpClient; diff --git a/network-client-okhttp/src/main/java/io/ably/lib/network/OkHttpUtils.java b/network-client-okhttp/src/main/java/io/ably/pubsub/network/OkHttpUtils.java similarity index 97% rename from network-client-okhttp/src/main/java/io/ably/lib/network/OkHttpUtils.java rename to network-client-okhttp/src/main/java/io/ably/pubsub/network/OkHttpUtils.java index 2bd566153..f101b3885 100644 --- a/network-client-okhttp/src/main/java/io/ably/lib/network/OkHttpUtils.java +++ b/network-client-okhttp/src/main/java/io/ably/pubsub/network/OkHttpUtils.java @@ -1,7 +1,6 @@ -package io.ably.lib.network; +package io.ably.pubsub.network; import okhttp3.Credentials; -import okhttp3.Headers; import okhttp3.MediaType; import okhttp3.OkHttpClient; import okhttp3.Request; diff --git a/network-client-okhttp/src/main/java/io/ably/lib/network/OkHttpWebSocketClient.java b/network-client-okhttp/src/main/java/io/ably/pubsub/network/OkHttpWebSocketClient.java similarity index 98% rename from network-client-okhttp/src/main/java/io/ably/lib/network/OkHttpWebSocketClient.java rename to network-client-okhttp/src/main/java/io/ably/pubsub/network/OkHttpWebSocketClient.java index bcaaf1c1d..038c947b3 100644 --- a/network-client-okhttp/src/main/java/io/ably/lib/network/OkHttpWebSocketClient.java +++ b/network-client-okhttp/src/main/java/io/ably/pubsub/network/OkHttpWebSocketClient.java @@ -1,4 +1,4 @@ -package io.ably.lib.network; +package io.ably.pubsub.network; import okhttp3.OkHttpClient; import okhttp3.Request; diff --git a/network-client-okhttp/src/main/java/io/ably/lib/network/OkHttpWebSocketEngine.java b/network-client-okhttp/src/main/java/io/ably/pubsub/network/OkHttpWebSocketEngine.java similarity index 96% rename from network-client-okhttp/src/main/java/io/ably/lib/network/OkHttpWebSocketEngine.java rename to network-client-okhttp/src/main/java/io/ably/pubsub/network/OkHttpWebSocketEngine.java index 7715501ab..0624759f9 100644 --- a/network-client-okhttp/src/main/java/io/ably/lib/network/OkHttpWebSocketEngine.java +++ b/network-client-okhttp/src/main/java/io/ably/pubsub/network/OkHttpWebSocketEngine.java @@ -1,4 +1,4 @@ -package io.ably.lib.network; +package io.ably.pubsub.network; import okhttp3.OkHttpClient; import okhttp3.Request; diff --git a/network-client-okhttp/src/main/java/io/ably/lib/network/OkHttpWebSocketEngineFactory.java b/network-client-okhttp/src/main/java/io/ably/pubsub/network/OkHttpWebSocketEngineFactory.java similarity index 90% rename from network-client-okhttp/src/main/java/io/ably/lib/network/OkHttpWebSocketEngineFactory.java rename to network-client-okhttp/src/main/java/io/ably/pubsub/network/OkHttpWebSocketEngineFactory.java index 24b7dcf20..9e876d4d2 100644 --- a/network-client-okhttp/src/main/java/io/ably/lib/network/OkHttpWebSocketEngineFactory.java +++ b/network-client-okhttp/src/main/java/io/ably/pubsub/network/OkHttpWebSocketEngineFactory.java @@ -1,4 +1,4 @@ -package io.ably.lib.network; +package io.ably.pubsub.network; public class OkHttpWebSocketEngineFactory implements WebSocketEngineFactory { @Override diff --git a/pubsub-adapter/build.gradle.kts b/pubsub-adapter/build.gradle.kts index 66ab1f09f..31a4e1a8c 100644 --- a/pubsub-adapter/build.gradle.kts +++ b/pubsub-adapter/build.gradle.kts @@ -9,9 +9,9 @@ kotlin { } dependencies { - compileOnly(project(":java")) + compileOnly(project(":core")) testImplementation(kotlin("test")) - testImplementation(project(":java")) + testImplementation(project(":core")) testImplementation(libs.nanohttpd) testImplementation(libs.coroutine.core) testImplementation(libs.coroutine.test) diff --git a/pubsub-adapter/src/main/kotlin/com/ably/pubsub/Channel.kt b/pubsub-adapter/src/main/kotlin/com/ably/pubsub/Channel.kt index 4588e610b..6cf06b177 100644 --- a/pubsub-adapter/src/main/kotlin/com/ably/pubsub/Channel.kt +++ b/pubsub-adapter/src/main/kotlin/com/ably/pubsub/Channel.kt @@ -1,11 +1,11 @@ package com.ably.pubsub import com.ably.query.OrderBy -import io.ably.lib.types.* +import io.ably.pubsub.types.* /** * An interface representing a Channel in the Ably API. This serves as the base interface - * for both [RealtimeChannel] and [RestChannel], providing common channel functionality + * for [RealtimeChannel], providing common channel functionality * such as history retrieval and presence management. * * A channel is the medium through which messages are distributed. Channels can represent diff --git a/pubsub-adapter/src/main/kotlin/com/ably/pubsub/Channels.kt b/pubsub-adapter/src/main/kotlin/com/ably/pubsub/Channels.kt index cdc989924..46b37d46e 100644 --- a/pubsub-adapter/src/main/kotlin/com/ably/pubsub/Channels.kt +++ b/pubsub-adapter/src/main/kotlin/com/ably/pubsub/Channels.kt @@ -1,7 +1,7 @@ package com.ably.pubsub -import io.ably.lib.realtime.ChannelState -import io.ably.lib.types.ChannelOptions +import io.ably.pubsub.realtime.ChannelState +import io.ably.pubsub.types.ChannelOptions /** * Represents collection of managed Channel instances diff --git a/pubsub-adapter/src/main/kotlin/com/ably/pubsub/Client.kt b/pubsub-adapter/src/main/kotlin/com/ably/pubsub/Client.kt index 4ff48ed22..fb8fe10e8 100644 --- a/pubsub-adapter/src/main/kotlin/com/ably/pubsub/Client.kt +++ b/pubsub-adapter/src/main/kotlin/com/ably/pubsub/Client.kt @@ -3,10 +3,10 @@ package com.ably.pubsub import com.ably.query.OrderBy import com.ably.query.TimeUnit import com.ably.http.HttpMethod -import io.ably.lib.http.HttpCore -import io.ably.lib.push.Push -import io.ably.lib.rest.Auth -import io.ably.lib.types.* +import io.ably.pubsub.http.HttpCore +import io.ably.pubsub.push.Push +import io.ably.pubsub.http.Auth +import io.ably.pubsub.types.* /** * A client that offers a base interface to interact with Ably's API. diff --git a/pubsub-adapter/src/main/kotlin/com/ably/pubsub/Presence.kt b/pubsub-adapter/src/main/kotlin/com/ably/pubsub/Presence.kt index 268ffe78d..20550ed0b 100644 --- a/pubsub-adapter/src/main/kotlin/com/ably/pubsub/Presence.kt +++ b/pubsub-adapter/src/main/kotlin/com/ably/pubsub/Presence.kt @@ -1,7 +1,7 @@ package com.ably.pubsub import com.ably.query.OrderBy -import io.ably.lib.types.* +import io.ably.pubsub.types.* /** * Enables get historic presence set for a channel. diff --git a/pubsub-adapter/src/main/kotlin/com/ably/pubsub/RealtimeChannel.kt b/pubsub-adapter/src/main/kotlin/com/ably/pubsub/RealtimeChannel.kt index 691544ef3..a04f9e132 100644 --- a/pubsub-adapter/src/main/kotlin/com/ably/pubsub/RealtimeChannel.kt +++ b/pubsub-adapter/src/main/kotlin/com/ably/pubsub/RealtimeChannel.kt @@ -2,13 +2,13 @@ package com.ably.pubsub import com.ably.Subscription import com.ably.annotations.InternalAPI -import io.ably.lib.realtime.ChannelBase.MessageListener -import io.ably.lib.realtime.ChannelState -import io.ably.lib.realtime.CompletionListener -import io.ably.lib.types.ChannelOptions -import io.ably.lib.types.ChannelProperties -import io.ably.lib.types.ErrorInfo -import io.ably.lib.types.Message +import io.ably.pubsub.realtime.ChannelBase.MessageListener +import io.ably.pubsub.realtime.ChannelState +import io.ably.pubsub.realtime.CompletionListener +import io.ably.pubsub.types.ChannelOptions +import io.ably.pubsub.types.ChannelProperties +import io.ably.pubsub.types.ErrorInfo +import io.ably.pubsub.types.Message /** @@ -45,7 +45,7 @@ public interface RealtimeChannel : Channel { * Attach to this channel ensuring the channel is created in the Ably system and all messages published * on the channel are received by any channel listeners registered using [subscribe]. * Any resulting channel state change will be emitted to any listeners registered using the - * [io.ably.lib.util.EventEmitter.on] or [io.ably.lib.util.EventEmitter.once] methods. + * [io.ably.pubsub.util.EventEmitter.on] or [io.ably.pubsub.util.EventEmitter.once] methods. * As a convenience, `attach()` is called implicitly if [subscribe] for the channel is called, * or [RealtimePresence.enter] or [RealtimePresence.subscribe] are called on the [RealtimePresence] object for this channel. * @@ -56,7 +56,7 @@ public interface RealtimeChannel : Channel { /** * Detach from this channel. * Any resulting channel state change is emitted to any listeners registered using the - * [io.ably.lib.util.EventEmitter.on] or [io.ably.lib.util.EventEmitter.once] methods. + * [io.ably.pubsub.util.EventEmitter.on] or [io.ably.pubsub.util.EventEmitter.once] methods. * Once all clients globally have detached from the channel, the channel will be released in the Ably service within two minutes. * * Spec: RTL5e @@ -150,5 +150,5 @@ public interface RealtimeChannel : Channel { * This property will be removed once public API for new version of ably-java is stable */ @InternalAPI - public val javaChannel: io.ably.lib.realtime.Channel + public val javaChannel: io.ably.pubsub.realtime.Channel } diff --git a/pubsub-adapter/src/main/kotlin/com/ably/pubsub/RealtimeClient.kt b/pubsub-adapter/src/main/kotlin/com/ably/pubsub/RealtimeClient.kt index 2dfd2ee7c..9e1285884 100644 --- a/pubsub-adapter/src/main/kotlin/com/ably/pubsub/RealtimeClient.kt +++ b/pubsub-adapter/src/main/kotlin/com/ably/pubsub/RealtimeClient.kt @@ -1,8 +1,8 @@ package com.ably.pubsub import com.ably.annotations.InternalAPI -import io.ably.lib.realtime.AblyRealtime -import io.ably.lib.realtime.Connection +import io.ably.pubsub.realtime.PubSubRealtimeClient +import io.ably.pubsub.realtime.Connection /** * A client that extends the functionality of the {@link Client} and provides additional realtime-specific features. @@ -28,5 +28,5 @@ public interface RealtimeClient : Client { * This property will be removed once public API for new version of ably-java is stable */ @InternalAPI - public val javaClient: AblyRealtime + public val javaClient: PubSubRealtimeClient } diff --git a/pubsub-adapter/src/main/kotlin/com/ably/pubsub/RealtimePresence.kt b/pubsub-adapter/src/main/kotlin/com/ably/pubsub/RealtimePresence.kt index cbd00805e..d2f4a16b5 100644 --- a/pubsub-adapter/src/main/kotlin/com/ably/pubsub/RealtimePresence.kt +++ b/pubsub-adapter/src/main/kotlin/com/ably/pubsub/RealtimePresence.kt @@ -1,10 +1,10 @@ package com.ably.pubsub import com.ably.Subscription -import io.ably.lib.realtime.ChannelState -import io.ably.lib.realtime.CompletionListener -import io.ably.lib.realtime.Presence.PresenceListener -import io.ably.lib.types.PresenceMessage +import io.ably.pubsub.realtime.ChannelState +import io.ably.pubsub.realtime.CompletionListener +import io.ably.pubsub.realtime.Presence.PresenceListener +import io.ably.pubsub.types.PresenceMessage import java.util.* @@ -15,7 +15,7 @@ public interface RealtimePresence : Presence { /** * Retrieves the current members present on the channel and the metadata for each member, - * such as their [io.ably.lib.types.PresenceMessage.Action] and ID. + * such as their [io.ably.pubsub.types.PresenceMessage.Action] and ID. * Returns an array of [PresenceMessage] objects. * * Spec: RTP11 diff --git a/pubsub-adapter/src/main/kotlin/com/ably/pubsub/RestChannel.kt b/pubsub-adapter/src/main/kotlin/com/ably/pubsub/RestChannel.kt deleted file mode 100644 index 12e05e8b1..000000000 --- a/pubsub-adapter/src/main/kotlin/com/ably/pubsub/RestChannel.kt +++ /dev/null @@ -1,44 +0,0 @@ -package com.ably.pubsub - -import io.ably.lib.realtime.CompletionListener -import io.ably.lib.types.Message - -public interface RestChannel : Channel { - - /** - * Presence set for a channel. - */ - override val presence: RestPresence - - /** - * Publish a message on this channel - * - * @param name the event name - * @param data the message payload; see [io.ably.types.Data] for details of supported data types. - */ - public fun publish(name: String? = null, data: Any? = null) - - /** - * Publish list of messages on this channel. When there are - * multiple messages to be sent, it is more efficient to use this - * method to publish them in a single request, as compared with - * publishing via multiple independent requests. - * - * @param messages list of messages to publish. - */ - public fun publish(messages: List) - - /** - * Publish a message on this channel asynchronously - * - * @see [publish] - */ - public fun publishAsync(name: String? = null, data: Any? = null, listener: CompletionListener) - - /** - * Publish list of messages on this channel asynchronously - * - * @see [publish] - */ - public fun publishAsync(messages: List, listener: CompletionListener) -} diff --git a/pubsub-adapter/src/main/kotlin/com/ably/pubsub/RestClient.kt b/pubsub-adapter/src/main/kotlin/com/ably/pubsub/RestClient.kt deleted file mode 100644 index 2e0451db9..000000000 --- a/pubsub-adapter/src/main/kotlin/com/ably/pubsub/RestClient.kt +++ /dev/null @@ -1,9 +0,0 @@ -package com.ably.pubsub - -public interface RestClient : Client { - - /** - * Collection of [RestChannel] instances currently managed by the client - */ - override val channels: Channels -} diff --git a/pubsub-adapter/src/main/kotlin/com/ably/pubsub/RestPresence.kt b/pubsub-adapter/src/main/kotlin/com/ably/pubsub/RestPresence.kt deleted file mode 100644 index 40d0f4d73..000000000 --- a/pubsub-adapter/src/main/kotlin/com/ably/pubsub/RestPresence.kt +++ /dev/null @@ -1,36 +0,0 @@ -package com.ably.pubsub - -import io.ably.lib.types.* - -public interface RestPresence : Presence { - - /** - * Retrieves the current members present on the channel and the metadata for each member, - * such as their [io.ably.lib.types.PresenceMessage.Action] and ID. Returns a [PaginatedResult] object, - * containing an array of [PresenceMessage] objects. - * - * Spec: RSPa - * - * @param limit (RSP3a) - An upper limit on the number of messages returned. The default is 100, and the maximum is 1000. - * @param clientId (RSP3a2) - Filters the list of returned presence members by a specific client using its ID. - * @param connectionId (RSP3a3) - Filters the list of returned presence members by a specific connection using its ID. - * @return A [PaginatedResult] object containing an array of [PresenceMessage] objects. - */ - public fun get(limit: Int = 100, clientId: String? = null, connectionId: String? = null): PaginatedResult - - /** - * Asynchronously retrieves the current members present on the channel and the metadata for each member, - * such as their [io.ably.lib.types.PresenceMessage.Action] and ID. Returns a [PaginatedResult] object, - * containing an array of [PresenceMessage] objects. - * - * Spec: RSPa - * - * @param limit (RSP3a) - An upper limit on the number of messages returned. The default is 100, and the maximum is 1000. - * @param clientId (RSP3a2) - Filters the list of returned presence members by a specific client using its ID. - * @param connectionId (RSP3a3) - Filters the list of returned presence members by a specific connection using its ID. - * @param callback A Callback returning [AsyncPaginatedResult] object containing an array of [PresenceMessage] objects. - * This callback is invoked on a background thread. - */ - public fun getAsync(callback: Callback>, limit: Int = 100, clientId: String? = null, connectionId: String? = null) - -} diff --git a/pubsub-adapter/src/main/kotlin/com/ably/pubsub/WrapperSdkProxy.kt b/pubsub-adapter/src/main/kotlin/com/ably/pubsub/WrapperSdkProxy.kt index 175b89d18..73369f633 100644 --- a/pubsub-adapter/src/main/kotlin/com/ably/pubsub/WrapperSdkProxy.kt +++ b/pubsub-adapter/src/main/kotlin/com/ably/pubsub/WrapperSdkProxy.kt @@ -6,7 +6,7 @@ public interface SdkWrapperCompatible { /** * Creates a proxy client to be used to supply analytics information for Ably-authored SDKs. - * The proxy client shares the state of the `RealtimeClient` or `RestClient` instance on which this method is called. + * The proxy client shares the state of the `RealtimeClient` instance on which this method is called. * This method should only be called by Ably-authored SDKs. */ public fun createWrapperSdkProxy(options: WrapperSdkProxyOptions): T @@ -14,7 +14,3 @@ public interface SdkWrapperCompatible { public fun RealtimeClient.createWrapperSdkProxy(options: WrapperSdkProxyOptions): RealtimeClient = (this as SdkWrapperCompatible<*>).createWrapperSdkProxy(options) as RealtimeClient - -public fun RestClient.createWrapperSdkProxy(options: WrapperSdkProxyOptions): RestClient = - (this as SdkWrapperCompatible<*>).createWrapperSdkProxy(options) as RestClient - diff --git a/pubsub-adapter/src/main/kotlin/io/ably/lib/rest/RestChannelAdapter.kt b/pubsub-adapter/src/main/kotlin/io/ably/lib/rest/RestChannelAdapter.kt deleted file mode 100644 index 29a00d1c9..000000000 --- a/pubsub-adapter/src/main/kotlin/io/ably/lib/rest/RestChannelAdapter.kt +++ /dev/null @@ -1,38 +0,0 @@ -package io.ably.lib.rest - -import com.ably.pubsub.RestChannel -import com.ably.pubsub.RestPresence -import com.ably.query.OrderBy -import io.ably.lib.buildHistoryParams -import io.ably.lib.realtime.CompletionListener -import io.ably.lib.types.* - -internal class RestChannelAdapter(private val javaChannel: Channel) : RestChannel { - override val name: String - get() = javaChannel.name - - override val presence: RestPresence - get() = RestPresenceAdapter(javaChannel.presence) - - override fun publish(name: String?, data: Any?) = javaChannel.publish(name, data) - - override fun publish(messages: List) = javaChannel.publish(messages.toTypedArray()) - - override fun publishAsync(name: String?, data: Any?, listener: CompletionListener) = - javaChannel.publishAsync(name, data, listener) - - override fun publishAsync(messages: List, listener: CompletionListener) = - javaChannel.publishAsync(messages.toTypedArray(), listener) - - override fun history(start: Long?, end: Long?, limit: Int, orderBy: OrderBy): PaginatedResult = - javaChannel.history(buildHistoryParams(start, end, limit, orderBy).toTypedArray()) - - override fun historyAsync( - callback: Callback>, - start: Long?, - end: Long?, - limit: Int, - orderBy: OrderBy, - ) = - javaChannel.historyAsync(buildHistoryParams(start, end, limit, orderBy).toTypedArray(), callback) -} diff --git a/pubsub-adapter/src/main/kotlin/io/ably/lib/rest/RestChannelsAdapter.kt b/pubsub-adapter/src/main/kotlin/io/ably/lib/rest/RestChannelsAdapter.kt deleted file mode 100644 index 083a2ce2a..000000000 --- a/pubsub-adapter/src/main/kotlin/io/ably/lib/rest/RestChannelsAdapter.kt +++ /dev/null @@ -1,20 +0,0 @@ -package io.ably.lib.rest - -import com.ably.pubsub.Channels -import com.ably.pubsub.RestChannel -import io.ably.lib.types.ChannelOptions - -internal class RestChannelsAdapter(private val javaChannels: AblyBase.Channels) : Channels { - override fun contains(name: String): Boolean = javaChannels.containsKey(name) - - override fun get(name: String): RestChannel = RestChannelAdapter(javaChannels.get(name)) - - override fun get(name: String, options: ChannelOptions): RestChannel = - RestChannelAdapter(javaChannels.get(name, options)) - - override fun release(name: String) = javaChannels.release(name) - - override fun iterator(): Iterator = iterator { - javaChannels.entrySet().forEach { yield(RestChannelAdapter(it.value)) } - } -} diff --git a/pubsub-adapter/src/main/kotlin/io/ably/lib/rest/RestClientAdapter.kt b/pubsub-adapter/src/main/kotlin/io/ably/lib/rest/RestClientAdapter.kt deleted file mode 100644 index c9b6c47f2..000000000 --- a/pubsub-adapter/src/main/kotlin/io/ably/lib/rest/RestClientAdapter.kt +++ /dev/null @@ -1,72 +0,0 @@ -package io.ably.lib.rest - -import com.ably.http.HttpMethod -import com.ably.pubsub.* -import com.ably.query.OrderBy -import com.ably.query.TimeUnit -import io.ably.lib.buildStatsParams -import io.ably.lib.http.HttpCore -import io.ably.lib.push.Push -import io.ably.lib.types.* - -/** - * Wrapper for Rest client - */ -public fun RestClient(javaClient: AblyRest): RestClient = RestClientAdapter(javaClient) - -internal class RestClientAdapter(private val javaClient: AblyRest) : RestClient, SdkWrapperCompatible { - override val channels: Channels - get() = RestChannelsAdapter(javaClient.channels) - override val auth: Auth - get() = javaClient.auth - override val options: ClientOptions - get() = javaClient.options - override val push: Push - get() = javaClient.push - - override fun time(): Long = javaClient.time() - - override fun timeAsync(callback: Callback) = javaClient.timeAsync(callback) - - override fun stats( - start: Long?, - end: Long?, - limit: Int, - orderBy: OrderBy, - unit: TimeUnit - ): PaginatedResult = javaClient.stats(buildStatsParams(start, end, limit, orderBy, unit).toTypedArray()) - - override fun statsAsync( - callback: Callback>, - start: Long?, - end: Long?, - limit: Int, - orderBy: OrderBy, - unit: TimeUnit - ) = javaClient.statsAsync(buildStatsParams(start, end, limit, orderBy, unit).toTypedArray(), callback) - - override fun request( - path: String, - method: HttpMethod, - params: List, - body: HttpCore.RequestBody?, - headers: List, - ) = javaClient.request(method.toString(), path, params.toTypedArray(), body, headers.toTypedArray())!! - - override fun requestAsync( - path: String, - callback: AsyncHttpPaginatedResponse.Callback, - method: HttpMethod, - params: List, - body: HttpCore.RequestBody?, - headers: List, - ) = javaClient.requestAsync(method.toString(), path, params.toTypedArray(), body, headers.toTypedArray(), callback) - - override fun close() = javaClient.close() - - override fun createWrapperSdkProxy(options: WrapperSdkProxyOptions): RestClient { - val httpCoreWithAgents = javaClient.httpCore.injectDynamicAgents(options.agents) - val httpModule = javaClient.http.exchangeHttpCore(httpCoreWithAgents) - return WrapperRestClient(javaClient, this, httpModule, options.agents) - } -} diff --git a/pubsub-adapter/src/main/kotlin/io/ably/lib/rest/RestClientUtils.kt b/pubsub-adapter/src/main/kotlin/io/ably/lib/rest/RestClientUtils.kt deleted file mode 100644 index d3b57bc42..000000000 --- a/pubsub-adapter/src/main/kotlin/io/ably/lib/rest/RestClientUtils.kt +++ /dev/null @@ -1,46 +0,0 @@ -package io.ably.lib.rest - -import com.ably.annotations.InternalAPI -import io.ably.lib.http.Http -import io.ably.lib.http.HttpCore -import io.ably.lib.types.* - -@InternalAPI -@Suppress("EXTENSION_SHADOWED_BY_MEMBER") -public fun AblyBase.time(http: Http): Long = time(http) - -@InternalAPI -@Suppress("EXTENSION_SHADOWED_BY_MEMBER") -public fun AblyBase.timeAsync(http: Http, callback: Callback): Unit = timeAsync(http, callback) - -@InternalAPI -@Suppress("EXTENSION_SHADOWED_BY_MEMBER") -public fun AblyBase.stats(http: Http, params: Array): PaginatedResult = stats(http, params) - -@InternalAPI -@Suppress("EXTENSION_SHADOWED_BY_MEMBER") -public fun AblyBase.statsAsync(http: Http, params: Array, callback: Callback>): Unit = - this.statsAsync(http, params, callback) - -@InternalAPI -@Suppress("EXTENSION_SHADOWED_BY_MEMBER") -public fun AblyBase.request( - http: Http, - method: String, - path: String, - params: Array?, - body: HttpCore.RequestBody?, - headers: Array? -): HttpPaginatedResponse = this.request(http, method, path, params, body, headers) - -@InternalAPI -@Suppress("EXTENSION_SHADOWED_BY_MEMBER") -public fun AblyBase.requestAsync( - http: Http, - method: String?, - path: String?, - params: Array?, - body: HttpCore.RequestBody?, - headers: Array?, - callback: AsyncHttpPaginatedResponse.Callback? -): Unit = this.requestAsync(http, method, path, params, body, headers, callback) diff --git a/pubsub-adapter/src/main/kotlin/io/ably/lib/rest/RestPresenceAdapter.kt b/pubsub-adapter/src/main/kotlin/io/ably/lib/rest/RestPresenceAdapter.kt deleted file mode 100644 index 1b4267b09..000000000 --- a/pubsub-adapter/src/main/kotlin/io/ably/lib/rest/RestPresenceAdapter.kt +++ /dev/null @@ -1,39 +0,0 @@ -package io.ably.lib.rest - -import com.ably.pubsub.RestPresence -import com.ably.query.OrderBy -import io.ably.lib.buildHistoryParams -import io.ably.lib.buildRestPresenceParams -import io.ably.lib.rest.ChannelBase.Presence -import io.ably.lib.types.AsyncPaginatedResult -import io.ably.lib.types.Callback -import io.ably.lib.types.PaginatedResult -import io.ably.lib.types.PresenceMessage - -internal class RestPresenceAdapter(private val javaPresence: Presence) : RestPresence { - override fun get( - limit: Int, - clientId: String?, - connectionId: String?, - ): PaginatedResult = - javaPresence.get(buildRestPresenceParams(limit, clientId, connectionId).toTypedArray()) - - override fun getAsync( - callback: Callback>, limit: Int, - clientId: String?, - connectionId: String?, - ) = - javaPresence.getAsync(buildRestPresenceParams(limit, clientId, connectionId).toTypedArray(), callback) - - override fun history(start: Long?, end: Long?, limit: Int, orderBy: OrderBy): PaginatedResult = - javaPresence.history(buildHistoryParams(start, end, limit, orderBy).toTypedArray()) - - override fun historyAsync( - callback: Callback>, - start: Long?, - end: Long?, - limit: Int, - orderBy: OrderBy, - ) = - javaPresence.historyAsync(buildHistoryParams(start, end, limit, orderBy).toTypedArray(), callback) -} diff --git a/pubsub-adapter/src/main/kotlin/io/ably/lib/rest/WrapperRestClient.kt b/pubsub-adapter/src/main/kotlin/io/ably/lib/rest/WrapperRestClient.kt deleted file mode 100644 index 6cf3c2dc0..000000000 --- a/pubsub-adapter/src/main/kotlin/io/ably/lib/rest/WrapperRestClient.kt +++ /dev/null @@ -1,138 +0,0 @@ -package io.ably.lib.rest - -import com.ably.http.HttpMethod -import com.ably.pubsub.* -import com.ably.query.OrderBy -import com.ably.query.TimeUnit -import io.ably.lib.buildHistoryParams -import io.ably.lib.buildRestPresenceParams -import io.ably.lib.buildStatsParams -import io.ably.lib.http.Http -import io.ably.lib.http.HttpCore -import io.ably.lib.realtime.CompletionListener -import io.ably.lib.rest.ChannelBase.Presence -import io.ably.lib.types.* - -internal class WrapperRestClient( - private val javaClient: AblyRest, - private val adapter: RestClientAdapter, - private val httpModule: Http, - private val agents: Map, -) : SdkWrapperCompatible, RestClient by adapter { - override val channels: Channels - get() = WrapperRestChannels(javaClient.channels, httpModule) - - override fun createWrapperSdkProxy(options: WrapperSdkProxyOptions): RestClient = - adapter.createWrapperSdkProxy(options.copy(agents = options.agents + agents)) - - override fun time(): Long = javaClient.time(httpModule) - - override fun timeAsync(callback: Callback) = javaClient.timeAsync(httpModule, callback) - - override fun stats( - start: Long?, - end: Long?, - limit: Int, - orderBy: OrderBy, - unit: TimeUnit - ): PaginatedResult = - javaClient.stats(httpModule, buildStatsParams(start, end, limit, orderBy, unit).toTypedArray()) - - override fun statsAsync( - callback: Callback>, - start: Long?, - end: Long?, - limit: Int, - orderBy: OrderBy, - unit: TimeUnit - ) = javaClient.statsAsync(httpModule, buildStatsParams(start, end, limit, orderBy, unit).toTypedArray(), callback) - - override fun request( - path: String, - method: HttpMethod, - params: List, - body: HttpCore.RequestBody?, - headers: List, - ) = javaClient.request(httpModule, method.toString(), path, params.toTypedArray(), body, headers.toTypedArray())!! - - override fun requestAsync( - path: String, - callback: AsyncHttpPaginatedResponse.Callback, - method: HttpMethod, - params: List, - body: HttpCore.RequestBody?, - headers: List, - ) = javaClient.requestAsync( - httpModule, - method.toString(), - path, - params.toTypedArray(), - body, - headers.toTypedArray(), - callback - ) - -} - -internal class WrapperRestChannels(private val javaChannels: AblyBase.Channels, private val httpModule: Http) : - Channels by RestChannelsAdapter(javaChannels) { - override fun get(name: String): RestChannel = WrapperRestChannel(javaChannels.get(name), httpModule) - - override fun get(name: String, options: ChannelOptions): RestChannel = - WrapperRestChannel(javaChannels.get(name, options), httpModule) -} - -internal class WrapperRestChannel(private val javaChannel: Channel, private val httpModule: Http) : - RestChannel by RestChannelAdapter(javaChannel) { - - override val presence: RestPresence - get() = WrapperRestPresence(javaChannel.presence, httpModule) - - override fun publish(name: String?, data: Any?) = javaChannel.publish(httpModule, name, data) - - override fun publish(messages: List) = javaChannel.publish(httpModule, messages.toTypedArray()) - - override fun publishAsync(name: String?, data: Any?, listener: CompletionListener) = - javaChannel.publishAsync(httpModule, name, data, listener) - - override fun publishAsync(messages: List, listener: CompletionListener) = - javaChannel.publishAsync(httpModule, messages.toTypedArray(), listener) - - override fun history(start: Long?, end: Long?, limit: Int, orderBy: OrderBy): PaginatedResult = - javaChannel.history(httpModule, buildHistoryParams(start, end, limit, orderBy).toTypedArray()) - - override fun historyAsync( - callback: Callback>, - start: Long?, - end: Long?, - limit: Int, - orderBy: OrderBy, - ) = - javaChannel.historyAsync(httpModule, buildHistoryParams(start, end, limit, orderBy).toTypedArray(), callback) -} - -internal class WrapperRestPresence(private val javaPresence: Presence, private val httpModule: Http) : - RestPresence by RestPresenceAdapter(javaPresence) { - override fun get(limit: Int, clientId: String?, connectionId: String?): PaginatedResult = - javaPresence.get(buildRestPresenceParams(limit, clientId, connectionId).toTypedArray()) - - override fun getAsync( - callback: Callback>, - limit: Int, - clientId: String?, - connectionId: String? - ) = - javaPresence.getAsync(buildRestPresenceParams(limit, clientId, connectionId).toTypedArray(), callback) - - override fun history(start: Long?, end: Long?, limit: Int, orderBy: OrderBy): PaginatedResult = - javaPresence.history(httpModule, buildHistoryParams(start, end, limit, orderBy).toTypedArray()) - - override fun historyAsync( - callback: Callback>, - start: Long?, - end: Long?, - limit: Int, - orderBy: OrderBy, - ) = - javaPresence.historyAsync(httpModule, buildHistoryParams(start, end, limit, orderBy).toTypedArray(), callback) -} diff --git a/pubsub-adapter/src/main/kotlin/io/ably/lib/Utils.kt b/pubsub-adapter/src/main/kotlin/io/ably/pubsub/Utils.kt similarity index 88% rename from pubsub-adapter/src/main/kotlin/io/ably/lib/Utils.kt rename to pubsub-adapter/src/main/kotlin/io/ably/pubsub/Utils.kt index a3371dbf1..052d66adc 100644 --- a/pubsub-adapter/src/main/kotlin/io/ably/lib/Utils.kt +++ b/pubsub-adapter/src/main/kotlin/io/ably/pubsub/Utils.kt @@ -1,8 +1,8 @@ -package io.ably.lib +package io.ably.pubsub import com.ably.query.OrderBy import com.ably.query.TimeUnit -import io.ably.lib.types.Param +import io.ably.pubsub.types.Param internal fun buildStatsParams( start: Long?, @@ -27,7 +27,7 @@ internal fun buildHistoryParams( add(Param("direction", orderBy.direction)) } -internal fun buildRestPresenceParams( +internal fun buildHttpPresenceParams( limit: Int, clientId: String?, connectionId: String?, diff --git a/pubsub-adapter/src/main/kotlin/io/ably/pubsub/http/PubSubBaseInternals.kt b/pubsub-adapter/src/main/kotlin/io/ably/pubsub/http/PubSubBaseInternals.kt new file mode 100644 index 000000000..96910c77a --- /dev/null +++ b/pubsub-adapter/src/main/kotlin/io/ably/pubsub/http/PubSubBaseInternals.kt @@ -0,0 +1,54 @@ +package io.ably.pubsub.http + +/* + * Package-private access bridge for PubSubBase, not part of the HTTP client API. + * + * PubSubBase declares time/stats/request as package-private, so WrapperRealtimeClient — which + * lives in the realtime package — cannot call them directly. These extensions sit in PubSubBase's + * own package and re-expose exactly those members, behind @InternalAPI so they are not a public + * contract. This file is why the realtime wrapper compiles; it is unrelated to the HTTP client + * surface that used to live alongside it. + */ + +import com.ably.annotations.InternalAPI +import io.ably.pubsub.types.* + +@InternalAPI +@Suppress("EXTENSION_SHADOWED_BY_MEMBER") +public fun PubSubBase.time(http: HttpRequester): Long = time(http) + +@InternalAPI +@Suppress("EXTENSION_SHADOWED_BY_MEMBER") +public fun PubSubBase.timeAsync(http: HttpRequester, callback: Callback): Unit = timeAsync(http, callback) + +@InternalAPI +@Suppress("EXTENSION_SHADOWED_BY_MEMBER") +public fun PubSubBase.stats(http: HttpRequester, params: Array): PaginatedResult = stats(http, params) + +@InternalAPI +@Suppress("EXTENSION_SHADOWED_BY_MEMBER") +public fun PubSubBase.statsAsync(http: HttpRequester, params: Array, callback: Callback>): Unit = + this.statsAsync(http, params, callback) + +@InternalAPI +@Suppress("EXTENSION_SHADOWED_BY_MEMBER") +public fun PubSubBase.request( + http: HttpRequester, + method: String, + path: String, + params: Array?, + body: HttpCore.RequestBody?, + headers: Array? +): HttpPaginatedResponse = this.request(http, method, path, params, body, headers) + +@InternalAPI +@Suppress("EXTENSION_SHADOWED_BY_MEMBER") +public fun PubSubBase.requestAsync( + http: HttpRequester, + method: String?, + path: String?, + params: Array?, + body: HttpCore.RequestBody?, + headers: Array?, + callback: AsyncHttpPaginatedResponse.Callback? +): Unit = this.requestAsync(http, method, path, params, body, headers, callback) diff --git a/pubsub-adapter/src/main/kotlin/io/ably/lib/realtime/RealtimeChannelAdapter.kt b/pubsub-adapter/src/main/kotlin/io/ably/pubsub/realtime/RealtimeChannelAdapter.kt similarity index 78% rename from pubsub-adapter/src/main/kotlin/io/ably/lib/realtime/RealtimeChannelAdapter.kt rename to pubsub-adapter/src/main/kotlin/io/ably/pubsub/realtime/RealtimeChannelAdapter.kt index 8a5e32abd..76e3fab06 100644 --- a/pubsub-adapter/src/main/kotlin/io/ably/lib/realtime/RealtimeChannelAdapter.kt +++ b/pubsub-adapter/src/main/kotlin/io/ably/pubsub/realtime/RealtimeChannelAdapter.kt @@ -1,12 +1,13 @@ -package io.ably.lib.realtime +package io.ably.pubsub.realtime import com.ably.Subscription import com.ably.annotations.InternalAPI import com.ably.pubsub.RealtimeChannel import com.ably.pubsub.RealtimePresence import com.ably.query.OrderBy -import io.ably.lib.buildHistoryParams -import io.ably.lib.types.* +import io.ably.pubsub.buildHistoryParams +import io.ably.pubsub.types.* +import io.ably.pubsub.util.Listeners @OptIn(InternalAPI::class) @@ -47,13 +48,18 @@ internal class RealtimeChannelAdapter(override val javaChannel: Channel) : Realt } } + /* + * The core publish overloads report a PublishResult, so a CompletionListener handed to this + * adapter is wrapped into one; the wrapper drops the result and calls the listener. + */ override fun publish(name: String?, data: Any?, listener: CompletionListener?) = - javaChannel.publish(name, data, listener) + javaChannel.publish(name, data, Listeners.fromCompletionListener(listener)) - override fun publish(message: Message, listener: CompletionListener?) = javaChannel.publish(message, listener) + override fun publish(message: Message, listener: CompletionListener?) = + javaChannel.publish(message, Listeners.fromCompletionListener(listener)) override fun publish(messages: List, listener: CompletionListener?) = - javaChannel.publish(messages.toTypedArray(), listener) + javaChannel.publish(messages.toTypedArray(), Listeners.fromCompletionListener(listener)) override fun setOptions(options: ChannelOptions) = javaChannel.setOptions(options) diff --git a/pubsub-adapter/src/main/kotlin/io/ably/lib/realtime/RealtimeChannelsAdapter.kt b/pubsub-adapter/src/main/kotlin/io/ably/pubsub/realtime/RealtimeChannelsAdapter.kt similarity index 83% rename from pubsub-adapter/src/main/kotlin/io/ably/lib/realtime/RealtimeChannelsAdapter.kt rename to pubsub-adapter/src/main/kotlin/io/ably/pubsub/realtime/RealtimeChannelsAdapter.kt index 0fe955b30..6fc20379f 100644 --- a/pubsub-adapter/src/main/kotlin/io/ably/lib/realtime/RealtimeChannelsAdapter.kt +++ b/pubsub-adapter/src/main/kotlin/io/ably/pubsub/realtime/RealtimeChannelsAdapter.kt @@ -1,10 +1,10 @@ -package io.ably.lib.realtime +package io.ably.pubsub.realtime import com.ably.pubsub.Channels import com.ably.pubsub.RealtimeChannel -import io.ably.lib.types.ChannelOptions +import io.ably.pubsub.types.ChannelOptions -internal class RealtimeChannelsAdapter(private val javaChannels: AblyRealtime.Channels) : Channels { +internal class RealtimeChannelsAdapter(private val javaChannels: PubSubRealtimeClient.Channels) : Channels { override fun contains(name: String): Boolean = javaChannels.containsKey(name) override fun get(name: String): RealtimeChannel = RealtimeChannelAdapter(javaChannels.get(name)) diff --git a/pubsub-adapter/src/main/kotlin/io/ably/lib/realtime/RealtimeClientAdapter.kt b/pubsub-adapter/src/main/kotlin/io/ably/pubsub/realtime/RealtimeClientAdapter.kt similarity index 79% rename from pubsub-adapter/src/main/kotlin/io/ably/lib/realtime/RealtimeClientAdapter.kt rename to pubsub-adapter/src/main/kotlin/io/ably/pubsub/realtime/RealtimeClientAdapter.kt index c95d8365a..38490204c 100644 --- a/pubsub-adapter/src/main/kotlin/io/ably/lib/realtime/RealtimeClientAdapter.kt +++ b/pubsub-adapter/src/main/kotlin/io/ably/pubsub/realtime/RealtimeClientAdapter.kt @@ -1,23 +1,25 @@ -package io.ably.lib.realtime +package io.ably.pubsub.realtime import com.ably.annotations.InternalAPI import com.ably.http.HttpMethod import com.ably.pubsub.* +import com.ably.pubsub.RealtimeClient +import io.ably.pubsub.realtime.PubSubRealtimeClient as CoreRealtimeClient import com.ably.query.OrderBy import com.ably.query.TimeUnit -import io.ably.lib.buildStatsParams -import io.ably.lib.http.HttpCore -import io.ably.lib.push.Push -import io.ably.lib.rest.Auth -import io.ably.lib.types.* +import io.ably.pubsub.buildStatsParams +import io.ably.pubsub.http.HttpCore +import io.ably.pubsub.push.Push +import io.ably.pubsub.http.Auth +import io.ably.pubsub.types.* /** * Wrapper for Realtime client */ -public fun RealtimeClient(javaClient: AblyRealtime): RealtimeClient = RealtimeClientAdapter(javaClient) +public fun RealtimeClient(javaClient: CoreRealtimeClient): RealtimeClient = RealtimeClientAdapter(javaClient) @OptIn(InternalAPI::class) -internal class RealtimeClientAdapter(override val javaClient: AblyRealtime) : RealtimeClient, SdkWrapperCompatible { +internal class RealtimeClientAdapter(override val javaClient: CoreRealtimeClient) : RealtimeClient, SdkWrapperCompatible { override val channels: Channels get() = RealtimeChannelsAdapter(javaClient.channels) override val connection: Connection diff --git a/pubsub-adapter/src/main/kotlin/io/ably/lib/realtime/RealtimePresenceAdapter.kt b/pubsub-adapter/src/main/kotlin/io/ably/pubsub/realtime/RealtimePresenceAdapter.kt similarity index 96% rename from pubsub-adapter/src/main/kotlin/io/ably/lib/realtime/RealtimePresenceAdapter.kt rename to pubsub-adapter/src/main/kotlin/io/ably/pubsub/realtime/RealtimePresenceAdapter.kt index 441c3dace..71a3ab376 100644 --- a/pubsub-adapter/src/main/kotlin/io/ably/lib/realtime/RealtimePresenceAdapter.kt +++ b/pubsub-adapter/src/main/kotlin/io/ably/pubsub/realtime/RealtimePresenceAdapter.kt @@ -1,10 +1,10 @@ -package io.ably.lib.realtime +package io.ably.pubsub.realtime import com.ably.Subscription import com.ably.pubsub.RealtimePresence import com.ably.query.OrderBy -import io.ably.lib.buildHistoryParams -import io.ably.lib.types.* +import io.ably.pubsub.buildHistoryParams +import io.ably.pubsub.types.* import java.util.* internal class RealtimePresenceAdapter(private val javaPresence: Presence) : RealtimePresence { diff --git a/pubsub-adapter/src/main/kotlin/io/ably/lib/realtime/WrapperRealtimeClient.kt b/pubsub-adapter/src/main/kotlin/io/ably/pubsub/realtime/WrapperRealtimeClient.kt similarity index 87% rename from pubsub-adapter/src/main/kotlin/io/ably/lib/realtime/WrapperRealtimeClient.kt rename to pubsub-adapter/src/main/kotlin/io/ably/pubsub/realtime/WrapperRealtimeClient.kt index 923204cb7..44e9aa33f 100644 --- a/pubsub-adapter/src/main/kotlin/io/ably/lib/realtime/WrapperRealtimeClient.kt +++ b/pubsub-adapter/src/main/kotlin/io/ably/pubsub/realtime/WrapperRealtimeClient.kt @@ -1,22 +1,24 @@ -package io.ably.lib.realtime +package io.ably.pubsub.realtime import com.ably.annotations.InternalAPI import com.ably.http.HttpMethod import com.ably.pubsub.* +import com.ably.pubsub.RealtimeClient +import io.ably.pubsub.realtime.PubSubRealtimeClient as CoreRealtimeClient import com.ably.query.OrderBy import com.ably.query.TimeUnit -import io.ably.lib.buildHistoryParams -import io.ably.lib.buildStatsParams -import io.ably.lib.http.Http -import io.ably.lib.http.HttpCore -import io.ably.lib.rest.* -import io.ably.lib.types.* +import io.ably.pubsub.buildHistoryParams +import io.ably.pubsub.buildStatsParams +import io.ably.pubsub.http.HttpRequester +import io.ably.pubsub.http.HttpCore +import io.ably.pubsub.http.* +import io.ably.pubsub.types.* @OptIn(InternalAPI::class) internal class WrapperRealtimeClient( - override val javaClient: AblyRealtime, + override val javaClient: CoreRealtimeClient, private val adapter: RealtimeClientAdapter, - private val httpModule: Http, + private val httpModule: HttpRequester, private val agents: Map, ) : SdkWrapperCompatible, RealtimeClient by adapter { @@ -75,8 +77,8 @@ internal class WrapperRealtimeClient( } internal class WrapperRealtimeChannels( - private val javaChannels: AblyRealtime.Channels, - private val httpModule: Http, + private val javaChannels: CoreRealtimeClient.Channels, + private val httpModule: HttpRequester, private val agents: Map, ) : Channels by RealtimeChannelsAdapter(javaChannels) { @@ -96,7 +98,7 @@ internal class WrapperRealtimeChannels( } @OptIn(InternalAPI::class) -internal class WrapperRealtimeChannel(override val javaChannel: Channel, private val httpModule: Http) : +internal class WrapperRealtimeChannel(override val javaChannel: Channel, private val httpModule: HttpRequester) : RealtimeChannel by RealtimeChannelAdapter(javaChannel) { override val presence: RealtimePresence @@ -115,7 +117,7 @@ internal class WrapperRealtimeChannel(override val javaChannel: Channel, private javaChannel.historyAsync(httpModule, buildHistoryParams(start, end, limit, orderBy).toTypedArray(), callback) } -internal class WrapperRealtimePresence(private val javaPresence: Presence, private val httpModule: Http) : +internal class WrapperRealtimePresence(private val javaPresence: Presence, private val httpModule: HttpRequester) : RealtimePresence by RealtimePresenceAdapter(javaPresence) { override fun history(start: Long?, end: Long?, limit: Int, orderBy: OrderBy): PaginatedResult = diff --git a/pubsub-adapter/src/test/kotlin/com/ably/Utils.kt b/pubsub-adapter/src/test/kotlin/com/ably/Utils.kt index e21f27910..9e37ee9a2 100644 --- a/pubsub-adapter/src/test/kotlin/com/ably/Utils.kt +++ b/pubsub-adapter/src/test/kotlin/com/ably/Utils.kt @@ -1,8 +1,8 @@ package com.ably -import io.ably.lib.realtime.AblyRealtime -import io.ably.lib.rest.AblyRest -import io.ably.lib.types.ClientOptions +import io.ably.pubsub.realtime.PubSubRealtimeClient +import io.ably.pubsub.realtime.RealtimeClientFactory +import io.ably.pubsub.types.ClientOptions import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.delay import kotlinx.coroutines.withContext @@ -19,28 +19,14 @@ suspend fun waitFor(timeoutInMs: Long = 10_000, block: suspend () -> Boolean) { } } -fun createAblyRealtime(port: Int): AblyRealtime { +fun createCoreRealtimeClient(port: Int): PubSubRealtimeClient { val options = ClientOptions("xxxxx:yyyyyyy").apply { this.port = port useBinaryProtocol = false - realtimeHost = "localhost" - restHost = "localhost" + endpoint = "localhost" tls = false autoConnect = false } - return AblyRealtime(options) -} - -fun createAblyRest(port: Int): AblyRest { - val options = ClientOptions("xxxxx:yyyyyyy").apply { - this.port = port - useBinaryProtocol = false - realtimeHost = "localhost" - restHost = "localhost" - tls = false - autoConnect = false - } - - return AblyRest(options) + return RealtimeClientFactory.create(options) } diff --git a/pubsub-adapter/src/test/kotlin/com/ably/pubsub/SdkWrapperAgentChannelParamTest.kt b/pubsub-adapter/src/test/kotlin/com/ably/pubsub/SdkWrapperAgentChannelParamTest.kt index dbf4ca9c6..f437155b5 100644 --- a/pubsub-adapter/src/test/kotlin/com/ably/pubsub/SdkWrapperAgentChannelParamTest.kt +++ b/pubsub-adapter/src/test/kotlin/com/ably/pubsub/SdkWrapperAgentChannelParamTest.kt @@ -1,12 +1,14 @@ package com.ably.pubsub -import io.ably.lib.realtime.AblyRealtime -import io.ably.lib.realtime.RealtimeClient -import io.ably.lib.realtime.RealtimeClientAdapter -import io.ably.lib.realtime.channelOptions -import io.ably.lib.types.ChannelMode -import io.ably.lib.types.ChannelOptions -import io.ably.lib.types.ClientOptions +import io.ably.pubsub.realtime.PubSubRealtimeClient +// the adapter factory function of the same name, no longer covered by the class import above +import io.ably.pubsub.realtime.RealtimeClient +import io.ably.pubsub.realtime.RealtimeClientAdapter +import io.ably.pubsub.realtime.RealtimeClientFactory +import io.ably.pubsub.realtime.channelOptions +import io.ably.pubsub.types.ChannelMode +import io.ably.pubsub.types.ChannelOptions +import io.ably.pubsub.types.ClientOptions import kotlinx.coroutines.test.runTest import kotlin.test.Test import kotlin.test.assertEquals @@ -17,7 +19,7 @@ class SdkWrapperAgentChannelParamTest { @Test fun `should add agent information to Realtime channels params`() = runTest { - val javaRealtimeClient = createAblyRealtime() + val javaRealtimeClient = createRealtimeClient() val realtimeClient = RealtimeClientAdapter(javaRealtimeClient) val wrapperSdkClient = realtimeClient.createWrapperSdkProxy(WrapperSdkProxyOptions(agents = mapOf("chat-android" to "0.1.0"))) @@ -40,7 +42,7 @@ class SdkWrapperAgentChannelParamTest { @Test fun `should add agent information to Realtime channels params when channel created with custom options`() = runTest { - val javaRealtimeClient = createAblyRealtime() + val javaRealtimeClient = createRealtimeClient() val realtimeClient = RealtimeClient(javaRealtimeClient) val wrapperSdkClient = realtimeClient.createWrapperSdkProxy(WrapperSdkProxyOptions(agents = mapOf("chat-android" to "0.1.0"))) @@ -81,9 +83,9 @@ class SdkWrapperAgentChannelParamTest { } } -private fun createAblyRealtime(): AblyRealtime { +private fun createRealtimeClient(): PubSubRealtimeClient { val options = ClientOptions("xxxxx:yyyyyyy").apply { autoConnect = false } - return AblyRealtime(options) + return RealtimeClientFactory.create(options) } diff --git a/pubsub-adapter/src/test/kotlin/com/ably/pubsub/SdkWrapperAgentHeaderTest.kt b/pubsub-adapter/src/test/kotlin/com/ably/pubsub/SdkWrapperAgentHeaderTest.kt index d91359b8c..a74a7c39d 100644 --- a/pubsub-adapter/src/test/kotlin/com/ably/pubsub/SdkWrapperAgentHeaderTest.kt +++ b/pubsub-adapter/src/test/kotlin/com/ably/pubsub/SdkWrapperAgentHeaderTest.kt @@ -2,13 +2,10 @@ package com.ably.pubsub import app.cash.turbine.test import com.ably.EmbeddedServer -import com.ably.createAblyRest -import com.ably.createAblyRealtime +import com.ably.createCoreRealtimeClient import com.ably.json import com.ably.waitFor -import io.ably.lib.BuildConfig -import io.ably.lib.realtime.RealtimeClient -import io.ably.lib.rest.RestClient +import io.ably.pubsub.BuildConfig import kotlinx.coroutines.test.runTest import org.junit.jupiter.api.AfterAll import org.junit.jupiter.api.BeforeAll @@ -27,7 +24,7 @@ class SdkWrapperAgentHeaderTest { server.servedRequests.test { wrapperSdkClient.time() assertEquals( - setOf("ably-java/${BuildConfig.VERSION}", "jre/${System.getProperty("java.version")}", "chat-android/0.1.0"), + setOf("ably-pubsub-java/${BuildConfig.VERSION}", "jre/${System.getProperty("java.version")}", "chat-android/0.1.0"), awaitItem().headers["ably-agent"]?.split(" ")?.toSet(), ) } @@ -35,7 +32,7 @@ class SdkWrapperAgentHeaderTest { server.servedRequests.test { realtimeClient.time() assertEquals( - setOf("ably-java/${BuildConfig.VERSION}", "jre/${System.getProperty("java.version")}"), + setOf("ably-pubsub-java/${BuildConfig.VERSION}", "jre/${System.getProperty("java.version")}"), awaitItem().headers["ably-agent"]?.split(" ")?.toSet(), ) } @@ -43,31 +40,31 @@ class SdkWrapperAgentHeaderTest { server.servedRequests.test { wrapperSdkClient.request("/time") assertEquals( - setOf("ably-java/${BuildConfig.VERSION}", "jre/${System.getProperty("java.version")}", "chat-android/0.1.0"), + setOf("ably-pubsub-java/${BuildConfig.VERSION}", "jre/${System.getProperty("java.version")}", "chat-android/0.1.0"), awaitItem().headers["ably-agent"]?.split(" ")?.toSet(), ) } } @Test - fun `should use additional agents in Rest wrapper SDK client calls`() = runTest { - val restClient = createRealtimeClient() + fun `should use additional agents in HTTP wrapper SDK client calls`() = runTest { + val httpClient = createRealtimeClient() val wrapperSdkClient = - restClient.createWrapperSdkProxy(WrapperSdkProxyOptions(agents = mapOf("chat-android" to "0.1.0"))) + httpClient.createWrapperSdkProxy(WrapperSdkProxyOptions(agents = mapOf("chat-android" to "0.1.0"))) server.servedRequests.test { wrapperSdkClient.time() assertEquals( - setOf("ably-java/${BuildConfig.VERSION}", "jre/${System.getProperty("java.version")}", "chat-android/0.1.0"), + setOf("ably-pubsub-java/${BuildConfig.VERSION}", "jre/${System.getProperty("java.version")}", "chat-android/0.1.0"), awaitItem().headers["ably-agent"]?.split(" ")?.toSet(), ) } server.servedRequests.test { - restClient.time() + httpClient.time() assertEquals( - setOf("ably-java/${BuildConfig.VERSION}", "jre/${System.getProperty("java.version")}"), + setOf("ably-pubsub-java/${BuildConfig.VERSION}", "jre/${System.getProperty("java.version")}"), awaitItem().headers["ably-agent"]?.split(" ")?.toSet(), ) } @@ -75,39 +72,7 @@ class SdkWrapperAgentHeaderTest { server.servedRequests.test { wrapperSdkClient.request("/time") assertEquals( - setOf("ably-java/${BuildConfig.VERSION}", "jre/${System.getProperty("java.version")}", "chat-android/0.1.0"), - awaitItem().headers["ably-agent"]?.split(" ")?.toSet(), - ) - } - } - - @Test - fun `should use additional agents in Rest wrapper SDK channel calls`() = runTest { - val restClient = createRestClient() - - val wrapperSdkClient = - restClient.createWrapperSdkProxy(WrapperSdkProxyOptions(agents = mapOf("chat-android" to "0.1.0"))) - - server.servedRequests.test { - wrapperSdkClient.channels.get("test").history() - assertEquals( - setOf("ably-java/${BuildConfig.VERSION}", "jre/${System.getProperty("java.version")}", "chat-android/0.1.0"), - awaitItem().headers["ably-agent"]?.split(" ")?.toSet(), - ) - } - - server.servedRequests.test { - restClient.channels.get("test").history() - assertEquals( - setOf("ably-java/${BuildConfig.VERSION}", "jre/${System.getProperty("java.version")}"), - awaitItem().headers["ably-agent"]?.split(" ")?.toSet(), - ) - } - - server.servedRequests.test { - wrapperSdkClient.channels.get("test").presence.history() - assertEquals( - setOf("ably-java/${BuildConfig.VERSION}", "jre/${System.getProperty("java.version")}", "chat-android/0.1.0"), + setOf("ably-pubsub-java/${BuildConfig.VERSION}", "jre/${System.getProperty("java.version")}", "chat-android/0.1.0"), awaitItem().headers["ably-agent"]?.split(" ")?.toSet(), ) } @@ -123,7 +88,7 @@ class SdkWrapperAgentHeaderTest { server.servedRequests.test { wrapperSdkClient.channels.get("test").history() assertEquals( - setOf("ably-java/${BuildConfig.VERSION}", "jre/${System.getProperty("java.version")}", "chat-android/0.1.0"), + setOf("ably-pubsub-java/${BuildConfig.VERSION}", "jre/${System.getProperty("java.version")}", "chat-android/0.1.0"), awaitItem().headers["ably-agent"]?.split(" ")?.toSet(), ) } @@ -131,7 +96,7 @@ class SdkWrapperAgentHeaderTest { server.servedRequests.test { realtimeClient.channels.get("test").history() assertEquals( - setOf("ably-java/${BuildConfig.VERSION}", "jre/${System.getProperty("java.version")}"), + setOf("ably-pubsub-java/${BuildConfig.VERSION}", "jre/${System.getProperty("java.version")}"), awaitItem().headers["ably-agent"]?.split(" ")?.toSet(), ) } @@ -139,7 +104,7 @@ class SdkWrapperAgentHeaderTest { server.servedRequests.test { wrapperSdkClient.channels.get("test").presence.history() assertEquals( - setOf("ably-java/${BuildConfig.VERSION}", "jre/${System.getProperty("java.version")}", "chat-android/0.1.0"), + setOf("ably-pubsub-java/${BuildConfig.VERSION}", "jre/${System.getProperty("java.version")}", "chat-android/0.1.0"), awaitItem().headers["ably-agent"]?.split(" ")?.toSet(), ) } @@ -169,8 +134,7 @@ class SdkWrapperAgentHeaderTest { server.stop() } - private fun createRealtimeClient(): RealtimeClient = RealtimeClient(createAblyRealtime(PORT)) - - private fun createRestClient(): RestClient = RestClient(createAblyRest(PORT)) + private fun createRealtimeClient(): RealtimeClient = + io.ably.pubsub.realtime.RealtimeClient(createCoreRealtimeClient(PORT)) } } diff --git a/pubsub-adapter/src/test/kotlin/io/ably/lib/realtime/ChannelUtils.kt b/pubsub-adapter/src/test/kotlin/io/ably/lib/realtime/ChannelUtils.kt deleted file mode 100644 index a99e5a67f..000000000 --- a/pubsub-adapter/src/test/kotlin/io/ably/lib/realtime/ChannelUtils.kt +++ /dev/null @@ -1,6 +0,0 @@ -package io.ably.lib.realtime - -import io.ably.lib.types.ChannelOptions - -val ChannelBase.channelOptions: ChannelOptions? - get() = options diff --git a/pubsub-adapter/src/test/kotlin/io/ably/lib/RequestsTest.kt b/pubsub-adapter/src/test/kotlin/io/ably/pubsub/RequestsTest.kt similarity index 87% rename from pubsub-adapter/src/test/kotlin/io/ably/lib/RequestsTest.kt rename to pubsub-adapter/src/test/kotlin/io/ably/pubsub/RequestsTest.kt index 5ecbebd96..d479cbeaf 100644 --- a/pubsub-adapter/src/test/kotlin/io/ably/lib/RequestsTest.kt +++ b/pubsub-adapter/src/test/kotlin/io/ably/pubsub/RequestsTest.kt @@ -1,11 +1,11 @@ -package io.ably.lib +package io.ably.pubsub import app.cash.turbine.test import com.ably.* -import io.ably.lib.realtime.AblyRealtime -import io.ably.lib.types.AsyncHttpPaginatedResponse -import io.ably.lib.types.ErrorInfo -import io.ably.lib.types.Param +import io.ably.pubsub.realtime.PubSubRealtimeClient +import io.ably.pubsub.types.AsyncHttpPaginatedResponse +import io.ably.pubsub.types.ErrorInfo +import io.ably.pubsub.types.Param import kotlinx.coroutines.suspendCancellableCoroutine import kotlinx.coroutines.test.runTest import org.junit.jupiter.api.AfterAll @@ -19,7 +19,7 @@ class RequestsTest { @Test fun `should encode params on pagination requests`() = runTest { - val client = createAblyRealtime() + val client = createRealtimeClient() server.servedRequests.test { val paginatedResult = client.request("GET", "/page", arrayOf(Param("foo", "b a r")), null, null) assertEquals(mapOf("foo" to "b a r"), awaitItem().params) @@ -30,7 +30,7 @@ class RequestsTest { @Test fun `should encode params on async pagination requests`() = runTest { - val client = createAblyRealtime() + val client = createRealtimeClient() server.servedRequests.test { val paginatedResult = suspendCancellableCoroutine { continuation -> client.requestAsync("GET", "/page", arrayOf(Param("foo", "b a r")), null, null, object : AsyncHttpPaginatedResponse.Callback { @@ -87,6 +87,6 @@ class RequestsTest { server.stop() } - private fun createAblyRealtime(): AblyRealtime = createAblyRealtime(PORT) + private fun createRealtimeClient(): PubSubRealtimeClient = createCoreRealtimeClient(PORT) } } diff --git a/pubsub-adapter/src/test/kotlin/io/ably/pubsub/realtime/ChannelUtils.kt b/pubsub-adapter/src/test/kotlin/io/ably/pubsub/realtime/ChannelUtils.kt new file mode 100644 index 000000000..10645f0e9 --- /dev/null +++ b/pubsub-adapter/src/test/kotlin/io/ably/pubsub/realtime/ChannelUtils.kt @@ -0,0 +1,6 @@ +package io.ably.pubsub.realtime + +import io.ably.pubsub.types.ChannelOptions + +val ChannelBase.channelOptions: ChannelOptions? + get() = options diff --git a/server/build.gradle.kts b/server/build.gradle.kts new file mode 100644 index 000000000..f9f2eceb7 --- /dev/null +++ b/server/build.gradle.kts @@ -0,0 +1,25 @@ +plugins { + alias(libs.plugins.maven.publish) + checkstyle + `java-library` +} + +java { + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 +} + +dependencies { + /* + * api, not implementation: the factories return io.ably.pubsub.http.PubSubHttpClient and + * io.ably.pubsub.realtime.PubSubRealtimeClient, and consumers configure them with io.ably.pubsub.types.*, + * so the core is part of this module's compile-time ABI. + */ + api(project(":core")) + testImplementation(libs.bundles.tests) +} + +tasks.register("runUnitTests") { + beforeTest(closureOf { logger.lifecycle("-> $this") }) + outputs.upToDateWhen { false } +} diff --git a/server/gradle.properties b/server/gradle.properties new file mode 100644 index 000000000..976318088 --- /dev/null +++ b/server/gradle.properties @@ -0,0 +1,4 @@ +POM_ARTIFACT_ID=server +POM_NAME=Ably Pub/Sub SDK for servers +POM_DESCRIPTION=Ably Pub/Sub SDK for server-side JVM applications. +POM_PACKAGING=jar diff --git a/server/src/main/java/io/ably/pubsub/server/PubSubServer.java b/server/src/main/java/io/ably/pubsub/server/PubSubServer.java new file mode 100644 index 000000000..0cfd0674c --- /dev/null +++ b/server/src/main/java/io/ably/pubsub/server/PubSubServer.java @@ -0,0 +1,660 @@ +package io.ably.pubsub.server; + +import io.ably.pubsub.push.Storage; +import io.ably.pubsub.realtime.PubSubRealtimeClient; +import io.ably.pubsub.realtime.RealtimeClientFactory; +import io.ably.pubsub.http.HttpClientFactory; +import io.ably.pubsub.http.PubSubHttpClient; +import io.ably.pubsub.http.Auth; +import io.ably.pubsub.types.AblyException; +import io.ably.pubsub.types.ClientOptions; +import io.ably.pubsub.types.Param; +import io.ably.pubsub.types.ProxyOptions; +import io.ably.pubsub.util.Log.LogHandler; +import io.ably.pubsub.util.Side; + +import java.util.Map; + +/** + * Entry point for the Ably Pub/Sub SDK for servers: applications running on infrastructure you + * control, whose traffic is exempt from monthly-active-user billing. + *

+ * Clients built here are the same {@link PubSubHttpClient} and {@link PubSubRealtimeClient} objects the core SDK + * has always returned, and behave identically. What the artifact adds is the choice itself: the + * dependency you declare and the factory you call state which side of the connection your code runs + * on, rather than leaving it to be inferred. + *

+ * If your code runs on an end-user device, use the {@code io.ably.pubsub:device} artifact instead. + * + *

{@code
+ * PubSubHttpClient http = PubSubServer.httpClientBuilder()
+ *     .key("xVLyHw.MHOCLg:...")
+ *     .build();
+ *
+ * PubSubRealtimeClient realtime = PubSubServer.realtimeClientBuilder()
+ *     .key("xVLyHw.MHOCLg:...")
+ *     .echoMessages(false)
+ *     .build();
+ * }
+ */ +public final class PubSubServer { + + private PubSubServer() { + } + + /** + * Creates a builder for a stateless HTTP client, which talks to Ably over plain HTTP requests + * without holding a connection open. + *

+ * This is the right choice for most server-side work: publishing, reading history, querying + * presence, issuing tokens and push administration. + * + * @return a new builder. + */ + public static HttpClientBuilder httpClientBuilder() { + return new HttpClientBuilder(); + } + + /** + * As {@link #httpClientBuilder()}, but starting from options the caller has already + * assembled, rather than from the builder's own empty set. + *

+ * This is for callers holding a {@link ClientOptions} they did not build here: an SDK + * layered on this package that takes options from its own user, or a test harness passing + * a {@link io.ably.pubsub.debug.DebugOptions} subclass. To supply an API key or token, prefer + * {@link ClientBuilder#key(String)} or {@link ClientBuilder#token(String)} on the no-arg + * builder over assembling options for it. + *

+ * The builder's setters still apply on top of what is passed here, and {@link + * HttpClientBuilder#build()} stamps the side-declaring agent entry as usual. The + * options object is handed to the client rather than copied, so later changes to it are not + * isolated from the built client, and {@code build()} replaces its {@code agents} map with + * the stamped one; pass {@link ClientOptions#copy()} if either matters. A {@code null} is + * carried through to {@code build()}, which surfaces the core constructor's own + * "no options provided" error. + * + * @param options the options to start from. + * @return a new builder over {@code options}. + */ + public static HttpClientBuilder httpClientBuilder(ClientOptions options) { + return new HttpClientBuilder(options); + } + + /** + * Creates a builder for a realtime client, which holds a persistent connection to Ably and can + * subscribe to messages and presence as they happen. + *

+ * Choose this over {@link #httpClientBuilder()} only when the server needs to receive messages + * live, rather than only send them. + * + * @return a new builder. + */ + public static RealtimeClientBuilder realtimeClientBuilder() { + return new RealtimeClientBuilder(); + } + + /** + * As {@link #realtimeClientBuilder()}, but starting from options the caller has already + * assembled, rather than from the builder's own empty set. + *

+ * This is for callers holding a {@link ClientOptions} they did not build here: an SDK + * layered on this package that takes options from its own user, or a test harness passing + * a {@link io.ably.pubsub.debug.DebugOptions} subclass. To supply an API key or token, prefer + * {@link ClientBuilder#key(String)} or {@link ClientBuilder#token(String)} on the no-arg + * builder over assembling options for it. + *

+ * The builder's setters still apply on top of what is passed here, and {@link + * RealtimeClientBuilder#build()} stamps the side-declaring agent entry as usual. The + * options object is handed to the client rather than copied, so later changes to it are not + * isolated from the built client, and {@code build()} replaces its {@code agents} map with + * the stamped one; pass {@link ClientOptions#copy()} if either matters. A {@code null} is + * carried through to {@code build()}, which surfaces the core constructor's own + * "no options provided" error. + * + * @param options the options to start from. + * @return a new builder over {@code options}. + */ + public static RealtimeClientBuilder realtimeClientBuilder(ClientOptions options) { + return new RealtimeClientBuilder(options); + } + + /** + * The options common to both server-side clients. One method per {@link ClientOptions} + * property that can affect a client of either kind; {@link RealtimeClientBuilder} adds the + * properties that only mean something for a persistent connection. + * + * @param the concrete builder type, so that chaining preserves it. + */ + public abstract static class ClientBuilder> { + + /** Accumulates the calls made on this builder; handed to the client as-is by build(). */ + final ClientOptions options; + + ClientBuilder() { + this(new ClientOptions()); + } + + ClientBuilder(ClientOptions options) { + this.options = options; + } + + @SuppressWarnings("unchecked") + private T self() { + return (T) this; + } + + /** + * Sets {@link Auth.AuthOptions#authCallback}. + * + * @param authCallback the value to set. + * @return this builder. + */ + public T authCallback(Auth.TokenCallback authCallback) { + options.authCallback = authCallback; + return self(); + } + + /** + * Sets {@link Auth.AuthOptions#authUrl}. + * + * @param authUrl the value to set. + * @return this builder. + */ + public T authUrl(String authUrl) { + options.authUrl = authUrl; + return self(); + } + + /** + * Sets {@link Auth.AuthOptions#authMethod}. + * + * @param authMethod the value to set. + * @return this builder. + */ + public T authMethod(String authMethod) { + options.authMethod = authMethod; + return self(); + } + + /** + * Sets {@link Auth.AuthOptions#key}. + * + * @param key the value to set. + * @return this builder. + */ + public T key(String key) { + options.key = key; + return self(); + } + + /** + * Sets {@link Auth.AuthOptions#token}. + * + * @param token the value to set. + * @return this builder. + */ + public T token(String token) { + options.token = token; + return self(); + } + + /** + * Sets {@link Auth.AuthOptions#tokenDetails}. + * + * @param tokenDetails the value to set. + * @return this builder. + */ + public T tokenDetails(Auth.TokenDetails tokenDetails) { + options.tokenDetails = tokenDetails; + return self(); + } + + /** + * Sets {@link Auth.AuthOptions#authHeaders}. + * + * @param authHeaders the value to set. + * @return this builder. + */ + public T authHeaders(Param[] authHeaders) { + options.authHeaders = authHeaders; + return self(); + } + + /** + * Sets {@link Auth.AuthOptions#authParams}. + * + * @param authParams the value to set. + * @return this builder. + */ + public T authParams(Param[] authParams) { + options.authParams = authParams; + return self(); + } + + /** + * Sets {@link Auth.AuthOptions#queryTime}. + * + * @param queryTime the value to set. + * @return this builder. + */ + public T queryTime(boolean queryTime) { + options.queryTime = queryTime; + return self(); + } + + /** + * Sets {@link Auth.AuthOptions#useTokenAuth}. + * + * @param useTokenAuth the value to set. + * @return this builder. + */ + public T useTokenAuth(boolean useTokenAuth) { + options.useTokenAuth = useTokenAuth; + return self(); + } + + /** + * Sets {@link ClientOptions#clientId}. + * + * @param clientId the value to set. + * @return this builder. + */ + public T clientId(String clientId) { + options.clientId = clientId; + return self(); + } + + /** + * Sets {@link ClientOptions#logLevel}. + * + * @param logLevel the value to set. + * @return this builder. + */ + public T logLevel(int logLevel) { + options.logLevel = logLevel; + return self(); + } + + /** + * Sets {@link ClientOptions#logHandler}. + * + * @param logHandler the value to set. + * @return this builder. + */ + public T logHandler(LogHandler logHandler) { + options.logHandler = logHandler; + return self(); + } + + /** + * Sets {@link ClientOptions#tls}. + * + * @param tls the value to set. + * @return this builder. + */ + public T tls(boolean tls) { + options.tls = tls; + return self(); + } + + /** + * Sets {@link ClientOptions#headers}. + * + * @param headers the value to set. + * @return this builder. + */ + public T headers(Map headers) { + options.headers = headers; + return self(); + } + + /** + * Sets {@link ClientOptions#endpoint}. + * + * @param endpoint the value to set. + * @return this builder. + */ + public T endpoint(String endpoint) { + options.endpoint = endpoint; + return self(); + } + + /** + * Sets {@link ClientOptions#port}. + * + * @param port the value to set. + * @return this builder. + */ + public T port(int port) { + options.port = port; + return self(); + } + + /** + * Sets {@link ClientOptions#tlsPort}. + * + * @param tlsPort the value to set. + * @return this builder. + */ + public T tlsPort(int tlsPort) { + options.tlsPort = tlsPort; + return self(); + } + + /** + * Sets {@link ClientOptions#useBinaryProtocol}. + * + * @param useBinaryProtocol the value to set. + * @return this builder. + */ + public T useBinaryProtocol(boolean useBinaryProtocol) { + options.useBinaryProtocol = useBinaryProtocol; + return self(); + } + + /** + * Sets {@link ClientOptions#proxy}. + * + * @param proxy the value to set. + * @return this builder. + */ + public T proxy(ProxyOptions proxy) { + options.proxy = proxy; + return self(); + } + + /** + * Sets {@link ClientOptions#idempotentRestPublishing}. + * + * @param idempotentRestPublishing the value to set. + * @return this builder. + */ + public T idempotentRestPublishing(boolean idempotentRestPublishing) { + options.idempotentRestPublishing = idempotentRestPublishing; + return self(); + } + + /** + * Sets {@link ClientOptions#httpOpenTimeout}. + * + * @param httpOpenTimeout the value to set. + * @return this builder. + */ + public T httpOpenTimeout(int httpOpenTimeout) { + options.httpOpenTimeout = httpOpenTimeout; + return self(); + } + + /** + * Sets {@link ClientOptions#httpRequestTimeout}. + * + * @param httpRequestTimeout the value to set. + * @return this builder. + */ + public T httpRequestTimeout(int httpRequestTimeout) { + options.httpRequestTimeout = httpRequestTimeout; + return self(); + } + + /** + * Sets {@link ClientOptions#httpMaxRetryDuration}. + * + * @param httpMaxRetryDuration the value to set. + * @return this builder. + */ + public T httpMaxRetryDuration(int httpMaxRetryDuration) { + options.httpMaxRetryDuration = httpMaxRetryDuration; + return self(); + } + + /** + * Sets {@link ClientOptions#httpMaxRetryCount}. + * + * @param httpMaxRetryCount the value to set. + * @return this builder. + */ + public T httpMaxRetryCount(int httpMaxRetryCount) { + options.httpMaxRetryCount = httpMaxRetryCount; + return self(); + } + + /** + * Sets {@link ClientOptions#fallbackHosts}. + * + * @param fallbackHosts the value to set. + * @return this builder. + */ + public T fallbackHosts(String[] fallbackHosts) { + options.fallbackHosts = fallbackHosts; + return self(); + } + + /** + * Sets {@link ClientOptions#fallbackRetryTimeout}. + * + * @param fallbackRetryTimeout the value to set. + * @return this builder. + */ + public T fallbackRetryTimeout(long fallbackRetryTimeout) { + options.fallbackRetryTimeout = fallbackRetryTimeout; + return self(); + } + + /** + * Sets {@link ClientOptions#defaultTokenParams}. + * + * @param defaultTokenParams the value to set. + * @return this builder. + */ + public T defaultTokenParams(Auth.TokenParams defaultTokenParams) { + options.defaultTokenParams = defaultTokenParams; + return self(); + } + + /** + * Sets {@link ClientOptions#asyncHttpThreadpoolSize}. + * + * @param asyncHttpThreadpoolSize the value to set. + * @return this builder. + */ + public T asyncHttpThreadpoolSize(int asyncHttpThreadpoolSize) { + options.asyncHttpThreadpoolSize = asyncHttpThreadpoolSize; + return self(); + } + + /** + * Sets {@link ClientOptions#pushFullWait}. + * + * @param pushFullWait the value to set. + * @return this builder. + */ + public T pushFullWait(boolean pushFullWait) { + options.pushFullWait = pushFullWait; + return self(); + } + + /** + * Sets {@link ClientOptions#localStorage}. + * + * @param localStorage the value to set. + * @return this builder. + */ + public T localStorage(Storage localStorage) { + options.localStorage = localStorage; + return self(); + } + + /** + * Sets {@link ClientOptions#addRequestIds}. + * + * @param addRequestIds the value to set. + * @return this builder. + */ + public T addRequestIds(boolean addRequestIds) { + options.addRequestIds = addRequestIds; + return self(); + } + + /** + * Sets {@link ClientOptions#agents}. + * + * @param agents the value to set. + * @return this builder. + */ + public T agents(Map agents) { + options.agents = agents; + return self(); + } + } + + /** + * Builds a stateless HTTP client. Obtain one from {@link PubSubServer#httpClientBuilder()}. + *

+ * Deliberately does not expose the realtime-only options, since an {@link PubSubHttpClient} never + * opens a connection for them to apply to. + */ + public static final class HttpClientBuilder extends ClientBuilder { + + HttpClientBuilder() { + } + + HttpClientBuilder(ClientOptions options) { + super(options); + } + + /** + * Builds the client. + * + * @return an {@link PubSubHttpClient}. + * @throws AblyException if the options are invalid, for example if no authentication + * parameters were supplied. + */ + public PubSubHttpClient build() throws AblyException { + return HttpClientFactory.create(Side.injectSideAgent(options, Side.SERVER_AGENT_IDENTIFIER)); + } + } + + /** + * Builds a realtime client. Obtain one from {@link PubSubServer#realtimeClientBuilder()}. + */ + public static final class RealtimeClientBuilder extends ClientBuilder { + + RealtimeClientBuilder() { + } + + RealtimeClientBuilder(ClientOptions options) { + super(options); + } + + /** + * Sets {@link ClientOptions#autoConnect}. + * + * @param autoConnect the value to set. + * @return this builder. + */ + public RealtimeClientBuilder autoConnect(boolean autoConnect) { + options.autoConnect = autoConnect; + return this; + } + + /** + * Sets {@link ClientOptions#queueMessages}. + * + * @param queueMessages the value to set. + * @return this builder. + */ + public RealtimeClientBuilder queueMessages(boolean queueMessages) { + options.queueMessages = queueMessages; + return this; + } + + /** + * Sets {@link ClientOptions#echoMessages}. + * + * @param echoMessages the value to set. + * @return this builder. + */ + public RealtimeClientBuilder echoMessages(boolean echoMessages) { + options.echoMessages = echoMessages; + return this; + } + + /** + * Sets {@link ClientOptions#recover}. + * + * @param recover the value to set. + * @return this builder. + */ + public RealtimeClientBuilder recover(String recover) { + options.recover = recover; + return this; + } + + /** + * Sets {@link ClientOptions#realtimeRequestTimeout}. + * + * @param realtimeRequestTimeout the value to set. + * @return this builder. + */ + public RealtimeClientBuilder realtimeRequestTimeout(long realtimeRequestTimeout) { + options.realtimeRequestTimeout = realtimeRequestTimeout; + return this; + } + + /** + * Sets {@link ClientOptions#disconnectedRetryTimeout}. + * + * @param disconnectedRetryTimeout the value to set. + * @return this builder. + */ + public RealtimeClientBuilder disconnectedRetryTimeout(long disconnectedRetryTimeout) { + options.disconnectedRetryTimeout = disconnectedRetryTimeout; + return this; + } + + /** + * Sets {@link ClientOptions#suspendedRetryTimeout}. + * + * @param suspendedRetryTimeout the value to set. + * @return this builder. + */ + public RealtimeClientBuilder suspendedRetryTimeout(long suspendedRetryTimeout) { + options.suspendedRetryTimeout = suspendedRetryTimeout; + return this; + } + + /** + * Sets {@link ClientOptions#channelRetryTimeout}. + * + * @param channelRetryTimeout the value to set. + * @return this builder. + */ + public RealtimeClientBuilder channelRetryTimeout(int channelRetryTimeout) { + options.channelRetryTimeout = channelRetryTimeout; + return this; + } + + /** + * Sets {@link ClientOptions#transportParams}. + * + * @param transportParams the value to set. + * @return this builder. + */ + public RealtimeClientBuilder transportParams(Param[] transportParams) { + options.transportParams = transportParams; + return this; + } + + /** + * Builds the client, which connects immediately unless {@link #autoConnect(boolean)} was + * set to false. + * + * @return an {@link PubSubRealtimeClient}. + * @throws AblyException if the options are invalid, for example if no authentication + * parameters were supplied. + */ + public PubSubRealtimeClient build() throws AblyException { + return RealtimeClientFactory.create(Side.injectSideAgent(options, Side.SERVER_AGENT_IDENTIFIER)); + } + } +} diff --git a/server/src/test/java/io/ably/pubsub/server/PubSubServerTest.java b/server/src/test/java/io/ably/pubsub/server/PubSubServerTest.java new file mode 100644 index 000000000..ddee3795c --- /dev/null +++ b/server/src/test/java/io/ably/pubsub/server/PubSubServerTest.java @@ -0,0 +1,175 @@ +package io.ably.pubsub.server; + +import com.sun.net.httpserver.HttpServer; +import io.ably.pubsub.realtime.PubSubRealtimeClient; +import io.ably.pubsub.http.PubSubHttpClient; +import io.ably.pubsub.types.AblyException; +import io.ably.pubsub.util.Side; +import org.junit.Test; + +import java.net.InetSocketAddress; +import java.nio.charset.StandardCharsets; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.atomic.AtomicReference; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNotSame; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +/** + * The agent entries asserted here are what the platform reads to classify traffic (and, on + * MAU-priced accounts, what earns the server exemption), so these tests are deliberately + * strict: if one fails, billing classification is broken, not just a header. + *

+ * The side entry is a versionless flag — a bare token on the wire, registered as such in the ably-common agents registry + * — so the assertions also fail if a version (or any {@code /suffix}) reappears on it. + */ +public class PubSubServerTest { + + private static final String FAKE_KEY = "fakeAppId.fakeKeyId:fakeKeySecret"; + private static final String FAKE_TOKEN = "fakeTokenString"; + + /** + * The stamped entry is present as a versionless flag, and the other side's is absent. + */ + private static void assertServerFlag(Map agents) { + assertTrue("expected the server side flag", agents.containsKey(Side.SERVER_AGENT_IDENTIFIER)); + assertNull("the side flag is versionless", agents.get(Side.SERVER_AGENT_IDENTIFIER)); + assertFalse("a server client must not carry the device entry", + agents.containsKey(Side.DEVICE_AGENT_IDENTIFIER)); + } + + @Test + public void httpClient_stampsServerAgent() throws AblyException { + PubSubHttpClient client = PubSubServer.httpClientBuilder().key(FAKE_KEY).build(); + assertServerFlag(client.options.agents); + } + + @Test + public void realtimeClient_stampsServerAgent() throws AblyException { + PubSubRealtimeClient client = PubSubServer + .realtimeClientBuilder() + .key(FAKE_KEY) + .autoConnect(false) + .build(); + assertServerFlag(client.options.agents); + } + + @Test + public void key_isCarriedAsKeyAlone() throws AblyException { + PubSubHttpClient client = PubSubServer.httpClientBuilder().key(FAKE_KEY).build(); + assertEquals(FAKE_KEY, client.options.key); + assertNull(client.options.token); + assertServerFlag(client.options.agents); + } + + @Test + public void token_isCarriedAsTokenAlone() throws AblyException { + PubSubHttpClient client = PubSubServer.httpClientBuilder().token(FAKE_TOKEN).build(); + assertEquals(FAKE_TOKEN, client.options.token); + assertNull(client.options.key); + assertServerFlag(client.options.agents); + } + + @Test + public void callerAgentEntries_arePreserved() throws AblyException { + Map agents = new HashMap<>(); + agents.put("some-sdk", "1.2.3"); + PubSubHttpClient client = PubSubServer + .httpClientBuilder() + .key(FAKE_KEY) + .agents(agents) + .build(); + assertEquals("1.2.3", client.options.agents.get("some-sdk")); + assertServerFlag(client.options.agents); + } + + @Test + public void callerCannotOverrideTheSideEntry() throws AblyException { + Map agents = new HashMap<>(); + agents.put(Side.SERVER_AGENT_IDENTIFIER, "not-the-real-form"); + PubSubHttpClient client = PubSubServer + .httpClientBuilder() + .key(FAKE_KEY) + .agents(agents) + .build(); + // The stamp replaces the caller's value: the flag is present and back to versionless. + assertServerFlag(client.options.agents); + } + + @Test + public void callersAgentsMap_isNotMutated() throws AblyException { + Map callerAgents = new HashMap<>(); + callerAgents.put("some-sdk", "1.2.3"); + PubSubHttpClient client = PubSubServer + .httpClientBuilder() + .key(FAKE_KEY) + .agents(callerAgents) + .build(); + assertNotSame("the stamp must go into a copy, not the caller's map", + callerAgents, client.options.agents); + assertEquals(1, callerAgents.size()); + assertFalse(callerAgents.containsKey(Side.SERVER_AGENT_IDENTIFIER)); + } + + @Test + public void noAuthParameters_getTheCoreConstructorsOwnError() { + try { + PubSubServer.httpClientBuilder().build(); + fail("expected the core's initialization error"); + } catch (AblyException e) { + assertEquals(40000, e.errorInfo.code); + } + } + + /** + * Wire-level assertion: the Ably-Agent header actually sent over HTTP carries the + * side-declaring flag as a bare token alongside the core's base identifier. This is the + * value billing classification reads. + */ + @Test + public void httpRequests_carryTheServerAgentHeaderOnTheWire() throws Exception { + AtomicReference observedAgentHeader = new AtomicReference<>(); + HttpServer httpServer = HttpServer.create(new InetSocketAddress("127.0.0.1", 0), 0); + httpServer.createContext("/time", exchange -> { + observedAgentHeader.set(exchange.getRequestHeaders().getFirst("Ably-Agent")); + byte[] body = "[1234567890000]".getBytes(StandardCharsets.UTF_8); + exchange.getResponseHeaders().add("Content-Type", "application/json"); + exchange.sendResponseHeaders(200, body.length); + exchange.getResponseBody().write(body); + exchange.close(); + }); + httpServer.start(); + try { + PubSubHttpClient client = PubSubServer + .httpClientBuilder() + .key(FAKE_KEY) + .tls(false) + .endpoint("127.0.0.1") + .port(httpServer.getAddress().getPort()) + .build(); + client.time(); + + String agentHeader = observedAgentHeader.get(); + assertNotNull("no Ably-Agent header observed", agentHeader); + List tokens = Arrays.asList(agentHeader.split(" ")); + // The flag must be present as a bare token: `name/anything` means the + // versionless stamp regressed (the registry entry is versionless). + assertTrue("missing bare side flag in: " + agentHeader, + tokens.contains(Side.SERVER_AGENT_IDENTIFIER)); + assertFalse("side flag must be versionless in: " + agentHeader, + agentHeader.contains(Side.SERVER_AGENT_IDENTIFIER + "/")); + assertTrue("missing core base identifier in: " + agentHeader, + agentHeader.contains("ably-pubsub-java/")); + } finally { + httpServer.stop(0); + } + } +} diff --git a/settings.gradle.kts b/settings.gradle.kts index dfd7150f4..3b23e33dc 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -6,10 +6,12 @@ pluginManagement { } } -rootProject.name = "ably-java" +rootProject.name = "ably-pubsub-java" -include("java") -include("android") +include("core") +include("core-android") +include("device") +include("server") include("gradle-lint") include("network-client-core") include("network-client-default") diff --git a/uts/README.md b/uts/README.md index 7d1b0820b..82d1d2d55 100644 --- a/uts/README.md +++ b/uts/README.md @@ -88,7 +88,7 @@ three example tests this guide walks through span all three tiers. The three examples above are `:uts`'s own **tier smoke tests** (§9–§11) — the reference shapes this guide walks through. The real, spec-derived suites live **by module**, in the module that owns the -code under test: realtime/rest under `:java` (`lib/src/test/kotlin/io/ably/lib/uts/…`), objects under +code under test: realtime/rest under `:java` (`lib/src/test/kotlin/io/ably/pubsub/uts/…`), objects under `:liveobjects` (`liveobjects/.../uts/…`). `:uts`'s own test tree holds only the tier smoke examples; so a feature's tests always sit with the SDK code they exercise (see §4.2 "Where every module's UTS tests live"). @@ -160,7 +160,7 @@ A big table mapping every features-spec group (`RSC`, `RTN`, `RTL`, `RTP`, …) cover it, with a per-tier summary (`unit:✓ proxy:✓`). This is the tracker for "what's done and what's missing". The reference tests this guide walks through correspond to these rows: - `RTN16` (connection recovery) → unit spec `connection_recovery_test.md` → - **`ConnectionRecoveryTest.kt`** (`:java`, `lib/src/test/kotlin/io/ably/lib/uts/unit/realtime/`). + **`ConnectionRecoveryTest.kt`** (`:java`, `lib/src/test/kotlin/io/ably/pubsub/uts/unit/realtime/`). - `RTL10d` (channel history) → direct-sandbox spec `realtime/integration/channel_history_test.md` → **`ChannelHistoryTest.kt`** (`:java`, `.../integration/standard/realtime/`). @@ -180,7 +180,7 @@ what's missing". The reference tests this guide walks through correspond to thes The `uts/` directory is a **standalone Gradle module** (`include("uts")` in `settings.gradle.kts`) that is the repo's **shared UTS test-support library** plus a small set of reference examples. Its -**main** source set *is* the shared test infrastructure — `uts/src/main/kotlin/io/ably/lib/uts/infra/` +**main** source set *is* the shared test infrastructure — `uts/src/main/kotlin/io/ably/pubsub/uts/infra/` — so any other Gradle module consumes it with a plain `testImplementation(project(":uts"))` (this module's own tests see it automatically). Its **test** source set holds only the three tier **smoke tests** (§9–§11): the permanent acceptance gate for the infra and the worked examples this guide @@ -208,11 +208,11 @@ java { } dependencies { - // The shared UTS infra (src/main/kotlin/io/ably/lib/uts/infra/**) — this module's main artifact, + // The shared UTS infra (src/main/kotlin/io/ably/pubsub/uts/infra/**) — this module's main artifact, // consumed elsewhere via testImplementation(project(":uts")). `api` for types that appear in // infra signatures; `implementation` for internals. Invariant I1: :uts never depends on // :liveobjects. - api(project(":java")) // the SDK + its types (DebugOptions, ProtocolMessage, …) + api(project(":core")) // the SDK + its types (DebugOptions, ProtocolMessage, …) api(project(":network-client-core")) // HttpEngine / WebSocketEngine SPIs the mocks implement implementation(libs.ktor.client.core) // proxy infra uses ktor internally — must NOT leak to consumers implementation(libs.ktor.client.cio) @@ -242,8 +242,8 @@ tasks.withType().configureEach { ) } -tasks.register("runUtsUnitTests") { filter { includeTestsMatching("io.ably.lib.uts.unit.*") } } -tasks.register("runUtsIntegrationTests") { filter { includeTestsMatching("io.ably.lib.uts.integration.*") } } +tasks.register("runUtsUnitTests") { filter { includeTestsMatching("io.ably.pubsub.uts.unit.*") } } +tasks.register("runUtsIntegrationTests") { filter { includeTestsMatching("io.ably.pubsub.uts.integration.*") } } kotlin { compilerOptions { jvmTarget.set(JvmTarget.JVM_1_8) } } ``` @@ -251,35 +251,35 @@ Takeaways: - `:uts` is a `java-library` + `kotlin.jvm` module. `java-test-fixtures` is **gone** — the infra is plain `src/main`, so consumers use `testImplementation(project(":uts"))` (no `testFixtures(...)` wrapper). `java-library` is what now supplies the `api` configuration. -- The module compiles to **Java 8** bytecode (source/target + `jvmTarget = JVM_1_8`), so `:java` +- The module compiles to **Java 8** bytecode (source/target + `jvmTarget = JVM_1_8`), so `:core` (which requests Java-8 variants) can consume it. **mockk is not a dependency** — the infra imports no test library at all. -- It depends on `:java` (the SDK under test) and `:network-client-core` (the pluggable transport SPIs +- It depends on `:core` (the SDK under test) and `:network-client-core` (the pluggable transport SPIs the mocks implement), both via `api` because they appear in infra signatures. - Tests are **Kotlin + JUnit 5**, using **kotlinx.coroutines** for async control and **Ktor** for the sandbox REST API and proxy control API. `junit-jupiter-params` (version from the JUnit BOM) adds **`@ParameterizedTest`** for the protocol-variant integration tests (§10.3). - `runUtsUnitTests` / `runUtsIntegrationTests` are package-filtered `Test` tasks (§13). The `--add-opens java.base/java.time` and `java.base/java.lang` flags grant the test runtime reflective - access into those JDK packages, mirroring `java/build.gradle.kts`. + access into those JDK packages, mirroring `core/build.gradle.kts`. - A system property carries an optional path to a **locally built** proxy binary (so you can test against an unreleased proxy). ### 4.2 Directory layout -Everything lives under the `io.ably.lib.uts` package, split cleanly between the **main** source set — +Everything lives under the `io.ably.pubsub.uts` package, split cleanly between the **main** source set — the shared **infrastructure** (`infra/`, no `@Test`s) — and the **test** source set — the three tier **smoke tests**. The infra is organised by tier: `infra/unit/` for mocked transports, and `infra/integration/` for real-backend helpers — the latter with an `infra/integration/proxy/` sub-package for the fault-injecting proxy — plus one shared `infra/Utils.kt` serving every tier: ```text -uts/src/main/kotlin/io/ably/lib/uts/ # ── shared infra, consumed via testImplementation(project(":uts")) ── +uts/src/main/kotlin/io/ably/pubsub/uts/ # ── shared infra, consumed via testImplementation(project(":uts")) ── └── infra/ # ── TEST INFRASTRUCTURE (no @Test methods) ── ├── Utils.kt # awaitState / awaitChannelState / pollUntil (shared) │ ├── unit/ # UNIT infra (mocked transports) - │ ├── ClientFactories.kt # TestRealtimeClient / TestRestClient / ClientOptionsBuilder + │ ├── ClientFactories.kt # TestRealtimeClient / TestHttpClient / ClientOptionsBuilder │ ├── MockWebSocket.kt # fake WS transport + WebSocketMockConfig + CONNECTED_MESSAGE │ ├── MockWebSocketEngineFactory.kt# plugs the mock into the SDK's WebSocketEngine SPI │ ├── MockHttpClient.kt # fake HTTP engine + HttpMockConfig @@ -298,7 +298,7 @@ uts/src/main/kotlin/io/ably/lib/uts/ # ── shared infra, consumed via ├── ProxyManager.kt # downloads/launches the uts-proxy binary └── ProxySession.kt # proxy session: rules, actions, log + connectThroughProxy -uts/src/test/kotlin/io/ably/lib/uts/ # ── the tier SMOKE TESTS (infra acceptance + worked examples) ── +uts/src/test/kotlin/io/ably/pubsub/uts/ # ── the tier SMOKE TESTS (infra acceptance + worked examples) ── ├── unit/ │ └── UnitInfraSmokeTest.kt # ← UNIT smoke: mock WS + HTTP + FakeClock (§9) └── integration/ @@ -321,8 +321,8 @@ The infra is shared, but the actual UTS suites live **in the module that owns th | Module | UTS tests | Location | Run with | |---|---|---|---| -| `:java` | realtime (and future rest) — unit, integration, proxy | `lib/src/test/kotlin/io/ably/lib/uts/{unit, integration/standard, integration/proxy}/realtime/` | `:java:runUtsUnitTests` / `:java:runUtsIntegrationTests` | -| `:liveobjects` | objects — unit, integration, proxy | `liveobjects/src/test/kotlin/io/ably/lib/liveobjects/uts/{unit, integration, proxy}/` | `:liveobjects:runLiveObjectsUnitTests` / `:liveobjects:runLiveObjectsIntegrationTests` | +| `:java` | realtime (and future rest) — unit, integration, proxy | `lib/src/test/kotlin/io/ably/pubsub/uts/{unit, integration/standard, integration/proxy}/realtime/` | `:java:runUtsUnitTests` / `:java:runUtsIntegrationTests` | +| `:liveobjects` | objects — unit, integration, proxy | `liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/uts/{unit, integration, proxy}/` | `:liveobjects:runLiveObjectsUnitTests` / `:liveobjects:runLiveObjectsIntegrationTests` | | `:uts` | **none** — shared infra + one smoke test per tier | `uts/src/main/.../infra/**` + `uts/src/test/.../{unit, integration/standard, integration/proxy}/` | `:uts:runUtsUnitTests` / `:uts:runUtsIntegrationTests` | Every consuming module gets the infra via `testImplementation(project(":uts"))`. The objects suites @@ -346,7 +346,7 @@ additionally reach `:liveobjects`-internal CRDT state (`InternalLiveMap`/`Intern ## 5. How a Test Reaches the SDK: the hook points A test can only mock transports because the SDK was designed with **pluggable seams**. They live on -`io.ably.lib.debug.DebugOptions` (a subclass of `ClientOptions`): +`io.ably.pubsub.debug.DebugOptions` (a subclass of `ClientOptions`): ```java public class DebugOptions extends ClientOptions { @@ -393,10 +393,10 @@ class ClientOptionsBuilder : DebugOptions("appId.keyId:keySecret") { fun enableFakeTimers(fakeClock: FakeClock) { clock = fakeClock } } -fun TestRealtimeClient(block: ClientOptionsBuilder.() -> Unit): AblyRealtime = - AblyRealtime(ClientOptionsBuilder().apply(block)) -fun TestRestClient(block: ClientOptionsBuilder.() -> Unit): AblyRest = - AblyRest(ClientOptionsBuilder().apply(block)) +fun TestRealtimeClient(block: ClientOptionsBuilder.() -> Unit): PubSubRealtimeClient = + RealtimeClientFactory.create(ClientOptionsBuilder().apply(block)) // or the PubSubServer builder; see below +fun TestHttpClient(block: ClientOptionsBuilder.() -> Unit): PubSubHttpClient = + HttpClientFactory.create(ClientOptionsBuilder().apply(block)) ``` - It seeds a **dummy API key** (`appId.keyId:keySecret`) — fine, because unit tests never hit a real @@ -550,13 +550,12 @@ firings. Common actions: `refuse_connection`, `suppress`, `replace`, `inject_to_ the proxy spec prescribes: ```kotlin fun ClientOptionsBuilder.connectThroughProxy(session: ProxySession) { - realtimeHost = session.proxyHost // "localhost" - restHost = session.proxyHost - port = session.proxyPort // the session's assigned port - tls = false // proxy serves plain HTTP/WS; TLS is only upstream + endpoint = session.proxyHost // "localhost" + port = session.proxyPort // the session's assigned port + tls = false // proxy serves plain HTTP/WS; TLS is only upstream } ``` -Explicit hosts auto-disable fallback hosts (REC2c2), so no `fallbackHosts` juggling is needed. +A hostname endpoint has no default fallback hosts (REC2c2), so no `fallbackHosts` juggling is needed. ### 7.3 `SandboxApp` — a throwaway app on the real sandbox Provisioning helper for the real backend (provisioned **directly**, not through the proxy, so it's @@ -568,16 +567,15 @@ independent of the fault rules): auto-expire). - The Ktor client retries only **idempotent GETs** (never re-POSTs `/apps`, to avoid duplicate apps). -- Owns the single sandbox **host** constant `SandboxApp.sandboxHost` - (`sandbox.realtime.ably-nonprod.net`) — the `nonprod:sandbox` endpoint used uniformly across the - realtime/objects/rest integration specs, resolved to a hostname. It's the single source of truth for - the upstream host: `ProxySession` defaults both its `realtimeHost` and `restHost` target to it, and - direct-sandbox clients set `realtimeHost` / `restHost` from it (sandbox realtime and REST are the - same host). +- Owns the sandbox constants: `SandboxApp.sandboxEndpoint` (`nonprod:sandbox`), the endpoint used + uniformly across the realtime/objects/rest integration specs, which direct-sandbox clients set as + their `endpoint`; and `SandboxApp.sandboxHost` (`sandbox.realtime.ably-nonprod.net`), the hostname + it resolves to. `ProxySession.create` takes an `endpoint` (default `sandboxEndpoint`) and resolves + it to the host it sends as both the proxy's upstream `realtimeHost` and `restHost` target. `SandboxApp` is the shared backbone of *both* integration kinds: **proxy** tests pair it with a `ProxySession`, while **direct sandbox** tests (`integration/standard//`) use it alone — -connecting straight to `SandboxApp.sandboxHost` with no proxy and no fault rules, for happy-path +connecting straight to `SandboxApp.sandboxEndpoint` with no proxy and no fault rules, for happy-path interop. --- @@ -607,7 +605,7 @@ thread-safe — always `CopyOnWriteArrayList`, never a plain `mutableListOf` (se A second `Utils.kt` under `infra/unit/` adds the `ConnectionDetails { … }` builder DSL so tests can write `ConnectionDetails { connectionKey = "key-1"; connectionStateTtl = 120000L }`. Since this file -no longer sits in the `io.ably.lib.types` package, it can't call `ConnectionDetails`'s package-private +no longer sits in the `io.ably.pubsub.types` package, it can't call `ConnectionDetails`'s package-private constructor directly — it obtains an instance **reflectively** (the same package-private-access technique used by `liveobjects/.../TestUtils.kt`). See Appendix B.1. @@ -615,7 +613,7 @@ technique used by `liveobjects/.../TestUtils.kt`). See Appendix B.1. ## 9. Walkthrough: the Unit Smoke Test (`UnitInfraSmokeTest`) -**File:** `uts/src/test/kotlin/io/ably/lib/uts/unit/UnitInfraSmokeTest.kt` (package `io.ably.lib.uts.unit`) +**File:** `uts/src/test/kotlin/io/ably/pubsub/uts/unit/UnitInfraSmokeTest.kt` (package `io.ably.pubsub.uts.unit`) **Tier:** Unit (mocked WebSocket + mocked HTTP, no network). **Purpose:** the permanent acceptance test for the unit-tier infra — it drives a real SDK through `MockWebSocket`, `MockHttpClient` and `FakeClock` end-to-end. It carries **no** `@UTS` marker (it is @@ -623,7 +621,7 @@ not derived from a spec) and must never trip the spec-parity tooling; it is the future unit-tier UTS test should take. > The real spec-derived unit suites this pattern scales to live in `:java` -> (`lib/src/test/kotlin/io/ably/lib/uts/unit/realtime/`, e.g. `ConnectionRecoveryTest`) and +> (`lib/src/test/kotlin/io/ably/pubsub/uts/unit/realtime/`, e.g. `ConnectionRecoveryTest`) and > `:liveobjects` — see §13. It has **three** `@Test` methods: two end-to-end transport tests (§9.1, §9.2) that between them exercise @@ -738,16 +736,16 @@ alone reaching quiescence. ## 10. Walkthrough: the Direct-Sandbox Smoke Test (`IntegrationInfraSmokeTest`) -**File:** `uts/src/test/kotlin/io/ably/lib/uts/integration/standard/IntegrationInfraSmokeTest.kt` (package `io.ably.lib.uts.integration.standard`) +**File:** `uts/src/test/kotlin/io/ably/pubsub/uts/integration/standard/IntegrationInfraSmokeTest.kt` (package `io.ably.pubsub.uts.integration.standard`) **Tier:** Direct-sandbox integration (real network, real Ably sandbox, **no** proxy, **no** fault injection). **Purpose:** the permanent acceptance test for the middle-tier infra — `SandboxApp` + -`TestRealtimeClient`/`TestRestClient` wired straight to the sandbox. No `@UTS` marker. +`TestRealtimeClient`/`TestHttpClient` wired straight to the sandbox. No `@UTS` marker. > The real spec-derived direct-sandbox suites this pattern scales to live in `:java` -> (`lib/src/test/kotlin/io/ably/lib/uts/integration/standard/realtime/`, e.g. `ChannelHistoryTest`) +> (`lib/src/test/kotlin/io/ably/pubsub/uts/integration/standard/realtime/`, e.g. `ChannelHistoryTest`) > and `:liveobjects` — see §13. -It talks to the real backend but connects *straight* to `SandboxApp.sandboxHost` — no `ProxyManager`, +It talks to the real backend but connects *straight* to `SandboxApp.sandboxEndpoint` — no `ProxyManager`, no `ProxySession`, no `connectThroughProxy`. It's the shape every happy-path interop spec (connect/publish/subscribe/history) follows. @@ -760,18 +758,17 @@ no `ProxySession`, no `connectThroughProxy`. It's the shape every happy-path int ``` ### 10.2 The clients — wired straight to the sandbox -Two tiny helpers point the **real** transports at the sandbox host (no proxy in between). Setting -explicit hosts auto-disables fallback hosts (REC2c2), so there's nothing else to configure: +Two tiny helpers point the **real** transports at the sandbox endpoint (no proxy in between), so +there's nothing else to configure: ```kotlin -private fun newRealtimeClient(useBinaryProtocol: Boolean): AblyRealtime = TestRealtimeClient { +private fun newRealtimeClient(useBinaryProtocol: Boolean): PubSubRealtimeClient = TestRealtimeClient { key = app.defaultKey - realtimeHost = SandboxApp.sandboxHost // sandbox.realtime.ably-nonprod.net - restHost = SandboxApp.sandboxHost + endpoint = SandboxApp.sandboxEndpoint // nonprod:sandbox this.useBinaryProtocol = useBinaryProtocol autoConnect = false } ``` -(`TestRealtimeClient`/`TestRestClient` are the same builders the unit tests use — here fed no mocks, so +(`TestRealtimeClient`/`TestHttpClient` are the same builders the unit tests use — here fed no mocks, so they drive the SDK's real network transport instead of a `MockWebSocket`.) ### 10.3 Protocol variants — the `@ParameterizedTest` pattern @@ -812,7 +809,7 @@ appear in the REST `history()`. The integration-specific techniques on show: - **Order assertion.** History defaults to newest-first, so `items[0]` is `event3` … `items[2]` is `event1`. **What this test teaches about the infra:** `SandboxApp`-only provisioning, the direct-sandbox client -wiring (`realtimeHost`/`restHost` from `SandboxApp.sandboxHost`, no proxy), the protocol-variant +wiring (`endpoint` from `SandboxApp.sandboxEndpoint`, no proxy), the protocol-variant `@ParameterizedTest`, awaiting a publish ack via `Callback`, and `pollUntil` over a real REST `history()` call. @@ -820,14 +817,14 @@ REST `history()` call. ## 11. Walkthrough: the Proxy Smoke Test (`ProxyInfraSmokeTest`) -**File:** `uts/src/test/kotlin/io/ably/lib/uts/integration/proxy/ProxyInfraSmokeTest.kt` (package `io.ably.lib.uts.integration.proxy`) +**File:** `uts/src/test/kotlin/io/ably/pubsub/uts/integration/proxy/ProxyInfraSmokeTest.kt` (package `io.ably.pubsub.uts.integration.proxy`) **Tier:** Proxy integration (real sandbox + uts-proxy). **Purpose:** the permanent acceptance test for the proxy infra — `ProxyManager` + `ProxySession` + `SandboxApp` + client wiring through the proxy, exercising **both** fault-injection styles. No `@UTS` marker. > The real spec-derived proxy suites this pattern scales to live in `:java` -> (`lib/src/test/kotlin/io/ably/lib/uts/integration/proxy/realtime/`, e.g. `AuthReauthTest`) and +> (`lib/src/test/kotlin/io/ably/pubsub/uts/integration/proxy/realtime/`, e.g. `AuthReauthTest`) and > `:liveobjects` — see §13. ### 11.1 Suite setup/teardown @@ -845,8 +842,9 @@ It has **two** `@Test` methods, one per fault-injection style. ### 11.2 Late imperative injection — `triggerAction` The first test creates a **rule-less pass-through** session, authenticates through the proxy (basic key -auth is TLS-only, so a token is signed locally by an `AblyRest(app.defaultKey)` in the `authCallback`), -and connects: +auth is TLS-only, so the `authCallback` signs a token locally with `AblyJwt` — a JWT rather than a +native TokenRequest so it can carry the `x-ably-clientType` claim the server leg needs, see the +token-auth note in §13), and connects: ```kotlin val session = ProxySession.create(rules = emptyList()) ``` @@ -895,7 +893,7 @@ right tool when the fault must land on a frame the test can't easily await; the ### 11.4 Teardown Both tests tear down in a nested `finally`: close the client, then always `session.close()` (`DELETE -/sessions/{id}`) and the token signer. +/sessions/{id}`). **What these tests teach about the infra:** `ProxyManager.ensureProxy` + `SandboxApp` setup, `connectThroughProxy`, **both** fault-injection styles (declarative `wsFrameToClientRule` at creation @@ -909,8 +907,8 @@ assertions** as the primary verification (`getLog()` → filter by `type`/`direc Deviations live **with their tests**, not in `:uts` (whose smoke tests carry none by design). There are two catalogues: -- `lib/src/test/kotlin/io/ably/lib/uts/deviations.md` — the **realtime/rest** tiers, hosted in `:java`. -- `liveobjects/src/test/kotlin/io/ably/lib/liveobjects/uts/deviations.md` — **all three objects tiers** +- `lib/src/test/kotlin/io/ably/pubsub/uts/deviations.md` — the **realtime/rest** tiers, hosted in `:java`. +- `liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/uts/deviations.md` — **all three objects tiers** (unit, integration, proxy), hosted in `:liveobjects`. Each entry records the **spec point**, **what the spec requires**, **what the SDK does**, the **root @@ -962,8 +960,8 @@ realtime suites; `:liveobjects` registers `runLiveObjectsUnitTests` / `runLiveOb | objects UTS unit | `./gradlew :liveobjects:runLiveObjectsUnitTests` | | objects UTS integration + proxy | `./gradlew :liveobjects:runLiveObjectsIntegrationTests` | -Each `runUts*` / `runLiveObjects*` task is package-filtered (`io.ably.lib.uts.unit.*` / -`io.ably.lib.uts.integration.*` for `:uts` and `:java`; `io.ably.lib.liveobjects.uts.*` for +Each `runUts*` / `runLiveObjects*` task is package-filtered (`io.ably.pubsub.uts.unit.*` / +`io.ably.pubsub.uts.integration.*` for `:uts` and `:java`; `io.ably.pubsub.liveobjects.uts.*` for `:liveobjects`). The `…IntegrationTests` tasks cover **both** the direct-sandbox (`integration/standard/`) and proxy (`integration/proxy/`) tiers — proxy tests additionally download/launch the uts-proxy. @@ -971,8 +969,8 @@ download/launch the uts-proxy. ```bash # All :uts smoke tests (every tier), or one class: ./gradlew :uts:test -./gradlew :uts:runUtsUnitTests --tests "io.ably.lib.uts.unit.UnitInfraSmokeTest" -./gradlew :java:runUtsIntegrationTests --tests "io.ably.lib.uts.integration.proxy.realtime.AuthReauthTest" +./gradlew :uts:runUtsUnitTests --tests "io.ably.pubsub.uts.unit.UnitInfraSmokeTest" +./gradlew :java:runUtsIntegrationTests --tests "io.ably.pubsub.uts.integration.proxy.realtime.AuthReauthTest" # Turn on the spec-correct (currently failing) deviation assertions (§12): RUN_DEVIATIONS=1 ./gradlew :java:runUtsUnitTests --tests "*ConnectionRecoveryTest*" @@ -995,6 +993,42 @@ RUN_DEVIATIONS=1 ./gradlew :java:runUtsUnitTests --tests "*ConnectionRecoveryTes `:java:runUtsIntegrationTests :uts:runUtsIntegrationTests`, and its `check-liveobjects` job runs `runLiveObjectsIntegrationTests`. +### Per-side package modes + +The suite constructs its clients through a single seam (`TestRealtimeClient` / `TestHttpClient` +in `infra/unit/ClientFactories.kt`), selected by the `uts.side` system property (or the +`UTS_SIDE` environment variable): + +```bash +./gradlew :uts:runUtsUnitTests # core (default): the core construction seam, no side declared +./gradlew :uts:runUtsUnitTests -Duts.side=server # io.ably.pubsub:server — the PubSubServer builders +``` + +The server builders only stamp the side-declaring agent entry (a versionless flag, per +ably/ably-common#361) and pass everything else through — `DebugOptions` included, whose `copy()` +override keeps the mock hooks — so every mode must pass identically. `SideModesTest` asserts each +mode's stamp so a broken seam cannot silently degrade the server leg into a duplicate core run. +CI runs both modes (`check.yml` and `integration-test.yml`). + +Unlike ably-js's UTS there is no `device` mode: `io.ably.pubsub:device` is an Android artifact, +so its door cannot run on the JVM this suite uses. Its stamping contract is covered by the +instrumentation tests in the `device` module (`emulate.yml`). + +**Token auth on the server leg.** Realtime rejects a token-authenticated connection that +declares the server side through the agent entry alone (error 40167: on token auth the side +must come from a signed `x-ably-clientType` token claim). The suite handles this per token +format, with nothing skipped: + +- **JWTs** can carry the claim already: tests that authenticate the client under test with a + token mint one via `AblyJwt` (HS256, JDK crypto), adding `x-ably-clientType=server` on the + server leg (see `AuthReauthTest` and `ProxyInfraSmokeTest`). +- **Native tokens** cannot carry the claim yet, so a client may not authenticate *itself* with + one while declaring the server side. `TokenRequestTest` therefore splits its clients across + the seam, matching how the feature is really used: the **minting** client (the + `createTokenRequest` surface under test) goes through the door on every leg, and the + **consuming** client — modelling the device the token was minted for — is always a plain + core client. + Notes: - `ProxyManager` **advises** running proxy suites single-fork (`maxParallelForks = 1`) because they share the control port (10100). This is not currently set in `uts/build.gradle.kts`; it isn't @@ -1059,7 +1093,7 @@ is talking to a real socket; in fact every byte is intercepted by the mock and s │ │ client.connect() ▲ awaitState(client, connected) │ │ ▼ │ │ │ ┌───────────┐ webSocketEngineFactory ┌──────────────────────────┐ │ - │ │ AblyRealtime (SDK :java) │──────────▶ │ MockWebSocketEngineFactory │ (implements SDK SPI) │ + │ │ PubSubRealtimeClient (SDK :java) │──────────▶ │ MockWebSocketEngineFactory │ (implements SDK SPI) │ │ │ ConnectionManager, etc. │ └─────────────┬────────────┘ │ │ └───────────┬────────────────┘ │ create() │ │ │ send(frame) ───────────────────────────▶ │ │ @@ -1100,7 +1134,7 @@ process, which forwards to the Ably sandbox and can inject faults on command. │ client.connect() (host=localhost, port=session.port, tls=false) │ ▼ │ ▼ ┌──────────────────┐ ws/http (plain) ┌───────────────────────┐ │ ┌───────────────────────┐ - │ AblyRealtime │ ◀──────────────────▶ │ uts-proxy │ ◀─┼▶│ Ably sandbox │ + │ PubSubRealtimeClient │ ◀──────────────────▶ │ uts-proxy │ ◀─┼▶│ Ably sandbox │ │ (REAL transport) │ │ • forwards traffic │ │ │ sandbox.realtime. │ └──────────────────┘ │ • applies rules │ │ │ ably-nonprod.net (TLS) │ ▲ │ • records event log │ │ └───────────────────────┘ @@ -1126,11 +1160,11 @@ A one-stop table of every Kotlin source file under `uts/src/main/` (the `infra/` `uts/src/test/` (the three tier smoke tests) and the SDK seams they use, so nothing is left implicit. -### B.1 Unit-test infrastructure — `io.ably.lib.uts.infra.unit` +### B.1 Unit-test infrastructure — `io.ably.pubsub.uts.infra.unit` | File | Key public surface | Role | |------|--------------------|------| -| `ClientFactories.kt` | `ClientOptionsBuilder` (extends `DebugOptions`), `TestRealtimeClient { }`, `TestRestClient { }`, `install(mock)`, `enableFakeTimers(clock)` | Entry point for building a mocked SDK client; seeds dummy key, forces JSON. | +| `ClientFactories.kt` | `ClientOptionsBuilder` (extends `DebugOptions`), `TestRealtimeClient { }`, `TestHttpClient { }`, `install(mock)`, `enableFakeTimers(clock)` | Entry point for building a mocked SDK client; seeds dummy key, forces JSON. | | `MockWebSocket.kt` | `MockWebSocket`, `WebSocketMockConfig` (`onConnectionAttempt`, `onMessageFromClient`, `onTextDataFrame`, `onBinaryDataFrame`), `events`, `installOn`, `awaitConnectionAttempt`, `awaitNextMessageFromClient`, `awaitClientClose`, `sendToClient`, `sendToClientAndClose`, `simulateDisconnect`, `reset`; top-level `MockWebSocket { }`, `CONNECTED_MESSAGE` | Fake realtime transport (callback + await styles). | | `MockWebSocketEngineFactory.kt` | `MockWebSocketEngineFactory`, `MockWebSocketEngine`, `MockWebSocketClient` (implement `WebSocketEngineFactory`/`Engine`/`Client`) | Adapts the mock to the SDK's WebSocket SPI; parses URL → host/port/tls/query. | | `MockHttpClient.kt` | `MockHttpClient`, `HttpMockConfig` (`onConnectionAttempt`, `onRequest`), `engine`, `installOn`, `awaitConnectionAttempt`, `awaitRequest`, `reset`; top-level `MockHttpClient { }` | Fake REST transport. | @@ -1143,22 +1177,22 @@ implicit. | `FakeClock.kt` | `FakeClock : Clock` (`advance(ms\|Duration)`, `pendingTaskCount(name)`, `currentTimeMillis`, `nanoTime`, `newTimer`, `waitOn`) | Virtual clock + virtual timers; deterministic time. | | `Utils.kt` | `ConnectionDetails { }` builder | Test-only `ConnectionDetails` DSL; instantiates the type via its **package-private constructor reflectively** (see §8). | -### B.2 Integration infrastructure — `io.ably.lib.uts.infra.integration` (and `…integration.proxy`) +### B.2 Integration infrastructure — `io.ably.pubsub.uts.infra.integration` (and `…integration.proxy`) | File | Key public surface | Role | |------|--------------------|------| | `proxy/ProxyManager.kt` | `object ProxyManager`: `ensureProxy(timeoutMs)`, `stopProxy()`, `CONTROL_PORT=10100`; pinned `PROXY_VERSION=v0.3.0` + per-arch checksums; `uts.proxy.localPath` override | Downloads/verifies/launches the `uts-proxy` binary; one shared process per run. *(package `…integration.proxy`)* | | `proxy/ProxySession.kt` | `class ProxySession` (`create(rules,port,timeoutMs,realtimeHost,restHost)`, `addRules`, `triggerAction`, `getLog(): List`, `close`, `sessionId`, `proxyPort`, `proxyHost`); `data class Event`; `typealias ProxyRule`; rule builders `wsConnectRule`/`wsFrameToClientRule`/`wsFrameToServerRule`/`httpRequestRule`; `ClientOptionsBuilder.connectThroughProxy(session)` | Typed client for the proxy control REST API + client wiring. *(package `…integration.proxy`)* | -| `SandboxApp.kt` | `class SandboxApp` (`create()`, `delete()`, `appId`, `defaultKey`, `keys`); `SandboxApp.sandboxHost` (`sandbox.realtime.ably-nonprod.net`) | Provisions/tears down a throwaway sandbox app from `ably-common`'s `test-app-setup.json`; owns the single upstream sandbox host constant. *(package `…integration`)* | +| `SandboxApp.kt` | `class SandboxApp` (`create()`, `delete()`, `appId`, `defaultKey`, `keys`); `SandboxApp.sandboxEndpoint` (`nonprod:sandbox`), `SandboxApp.sandboxHost` (`sandbox.realtime.ably-nonprod.net`) | Provisions/tears down a throwaway sandbox app from `ably-common`'s `test-app-setup.json`; owns the sandbox endpoint and upstream host constants. *(package `…integration`)* | ### B.3 Shared helpers & tests | File | Key public surface | Role | |------|--------------------|------| -| `infra/Utils.kt` | `awaitState(client,target,timeout=5s)`, `awaitChannelState(channel,target,timeout=5s)`, `pollUntil(timeout=15s,interval=100ms){ }` | Shared wall-clock coroutine waits (package `io.ably.lib.uts.infra`); listener registered before state check. | -| `unit/UnitInfraSmokeTest.kt` | 3 `@Test`s: full mock-WS lifecycle (await style), token-auth via mock HTTP (callback WS), FakeClock run-to-quiescence | Unit-tier infra acceptance (`io.ably.lib.uts.unit`) — MockWebSocket/MockHttpClient/FakeClock end-to-end. **No** `@UTS`. | -| `integration/standard/IntegrationInfraSmokeTest.kt` | 1 `@ParameterizedTest` × {JSON, msgpack} | Direct-sandbox infra acceptance (`io.ably.lib.uts.integration.standard`) — SandboxApp + realtime/REST round-trip, awaited publish + `pollUntil` on `history()`. **No** `@UTS`. | -| `integration/proxy/ProxyInfraSmokeTest.kt` | 2 `@Test`s: late imperative disconnect, declarative ws-frame rule | Proxy infra acceptance (`io.ably.lib.uts.integration.proxy`) — ProxyManager + ProxySession, both fault-injection styles, proxy-log asserts. **No** `@UTS`. | +| `infra/Utils.kt` | `awaitState(client,target,timeout=5s)`, `awaitChannelState(channel,target,timeout=5s)`, `pollUntil(timeout=15s,interval=100ms){ }` | Shared wall-clock coroutine waits (package `io.ably.pubsub.uts.infra`); listener registered before state check. | +| `unit/UnitInfraSmokeTest.kt` | 3 `@Test`s: full mock-WS lifecycle (await style), token-auth via mock HTTP (callback WS), FakeClock run-to-quiescence | Unit-tier infra acceptance (`io.ably.pubsub.uts.unit`) — MockWebSocket/MockHttpClient/FakeClock end-to-end. **No** `@UTS`. | +| `integration/standard/IntegrationInfraSmokeTest.kt` | 1 `@ParameterizedTest` × {JSON, msgpack} | Direct-sandbox infra acceptance (`io.ably.pubsub.uts.integration.standard`) — SandboxApp + realtime/REST round-trip, awaited publish + `pollUntil` on `history()`. **No** `@UTS`. | +| `integration/proxy/ProxyInfraSmokeTest.kt` | 2 `@Test`s: late imperative disconnect, declarative ws-frame rule | Proxy infra acceptance (`io.ably.pubsub.uts.integration.proxy`) — ProxyManager + ProxySession, both fault-injection styles, proxy-log asserts. **No** `@UTS`. | > **Coverage note:** this guide walks through the **three tier smoke tests** — `UnitInfraSmokeTest` > (unit, §9), `IntegrationInfraSmokeTest` (direct-sandbox, §10), and `ProxyInfraSmokeTest` (proxy, §11) @@ -1166,7 +1200,7 @@ implicit. > from. The infra under `infra/unit/` and `infra/integration/` is built out beyond what the smokes > exercise (full HTTP mock, all four rule builders, REST proxy wiring, etc.), anticipating the broader > UTS coverage catalogued in [`completion-status.md`](https://github.com/ably/specification/blob/main/uts/docs/completion-status.md). The real spec-derived suites that consume this -> infra live in `:java` (`lib/src/test/kotlin/io/ably/lib/uts/…`) and `:liveobjects` +> infra live in `:java` (`lib/src/test/kotlin/io/ably/pubsub/uts/…`) and `:liveobjects` > (`liveobjects/.../uts/…`) — see §13. --- @@ -1186,4 +1220,4 @@ implicit. | Integration helpers | `uts/src/main/.../uts/infra/integration/*` (+ `…/integration/proxy/*`) | | Async helpers | `uts/src/main/.../uts/infra/Utils.kt` (awaits), `…/infra/unit/Utils.kt` (ConnectionDetails builder) | | The three tier smoke tests | `uts/src/test/.../uts/unit/UnitInfraSmokeTest.kt`, `…/uts/integration/standard/IntegrationInfraSmokeTest.kt`, `…/uts/integration/proxy/ProxyInfraSmokeTest.kt` | -| Deviations | `lib/src/test/kotlin/io/ably/lib/uts/deviations.md` (realtime/rest, `:java`), `liveobjects/src/test/kotlin/io/ably/lib/liveobjects/uts/deviations.md` (objects, `:liveobjects`) | +| Deviations | `lib/src/test/kotlin/io/ably/pubsub/uts/deviations.md` (realtime/rest, `:java`), `liveobjects/src/test/kotlin/io/ably/pubsub/liveobjects/uts/deviations.md` (objects, `:liveobjects`) | diff --git a/uts/build.gradle.kts b/uts/build.gradle.kts index ffcc86c1d..24567a437 100644 --- a/uts/build.gradle.kts +++ b/uts/build.gradle.kts @@ -13,7 +13,10 @@ java { dependencies { // `api` for types that appear in infra signatures; `implementation` for internals. - api(project(":java")) + api(project(":core")) + // The server door package, so the suite can run through its side-stamping builders + // (`-Duts.side=server`) as well as the core constructors. See ClientFactories.kt. + implementation(project(":server")) api(project(":network-client-core")) // ktor stays implementation — the proxy infra uses it internally; it must NOT leak to consumers. implementation(libs.ktor.client.core) @@ -51,17 +54,27 @@ tasks.withType().configureEach { .orElse(providers.environmentVariable("UTS_PROXY_LOCAL_PATH")) .getOrElse(""), ) + + // Which package's entry points the suite constructs clients through: `core` (default) or + // `server` (the io.ably.pubsub:server builders). Forwarded explicitly for the same reason + // as uts.proxy.localPath above. See ClientFactories.kt. + systemProperty( + "uts.side", + providers.systemProperty("uts.side") + .orElse(providers.environmentVariable("UTS_SIDE")) + .getOrElse("core"), + ) } tasks.register("runUtsUnitTests") { filter { - includeTestsMatching("io.ably.lib.uts.unit.*") + includeTestsMatching("io.ably.pubsub.uts.unit.*") } } tasks.register("runUtsIntegrationTests") { filter { - includeTestsMatching("io.ably.lib.uts.integration.*") + includeTestsMatching("io.ably.pubsub.uts.integration.*") } } diff --git a/uts/src/main/kotlin/io/ably/lib/uts/infra/unit/ClientFactories.kt b/uts/src/main/kotlin/io/ably/lib/uts/infra/unit/ClientFactories.kt deleted file mode 100644 index 94a055cdd..000000000 --- a/uts/src/main/kotlin/io/ably/lib/uts/infra/unit/ClientFactories.kt +++ /dev/null @@ -1,24 +0,0 @@ -package io.ably.lib.uts.infra.unit - -import io.ably.lib.debug.DebugOptions -import io.ably.lib.realtime.AblyRealtime -import io.ably.lib.rest.AblyRest - -class ClientOptionsBuilder : DebugOptions("appId.keyId:keySecret") { - init { - useBinaryProtocol = false - } - - fun install(mock: MockWebSocket) = mock.installOn(this) - fun install(mock: MockHttpClient) = mock.installOn(this) - - fun enableFakeTimers(fakeClock: FakeClock) { - clock = fakeClock - } -} - -fun TestRealtimeClient(block: ClientOptionsBuilder.() -> Unit): AblyRealtime = - AblyRealtime(ClientOptionsBuilder().apply(block)) - -fun TestRestClient(block: ClientOptionsBuilder.() -> Unit): AblyRest = - AblyRest(ClientOptionsBuilder().apply(block)) diff --git a/uts/src/main/kotlin/io/ably/lib/uts/infra/Utils.kt b/uts/src/main/kotlin/io/ably/pubsub/uts/infra/Utils.kt similarity index 93% rename from uts/src/main/kotlin/io/ably/lib/uts/infra/Utils.kt rename to uts/src/main/kotlin/io/ably/pubsub/uts/infra/Utils.kt index ea3c94e6b..67bca2b33 100644 --- a/uts/src/main/kotlin/io/ably/lib/uts/infra/Utils.kt +++ b/uts/src/main/kotlin/io/ably/pubsub/uts/infra/Utils.kt @@ -1,11 +1,11 @@ -package io.ably.lib.uts.infra +package io.ably.pubsub.uts.infra -import io.ably.lib.realtime.AblyRealtime -import io.ably.lib.realtime.Channel -import io.ably.lib.realtime.ChannelState -import io.ably.lib.realtime.ChannelStateListener -import io.ably.lib.realtime.ConnectionState -import io.ably.lib.realtime.ConnectionStateListener +import io.ably.pubsub.realtime.PubSubRealtimeClient +import io.ably.pubsub.realtime.Channel +import io.ably.pubsub.realtime.ChannelState +import io.ably.pubsub.realtime.ChannelStateListener +import io.ably.pubsub.realtime.ConnectionState +import io.ably.pubsub.realtime.ConnectionStateListener import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.InternalCoroutinesApi import kotlinx.coroutines.delay @@ -32,7 +32,7 @@ import kotlin.time.Duration.Companion.seconds */ @OptIn(InternalCoroutinesApi::class) suspend fun awaitState( - client: AblyRealtime, + client: PubSubRealtimeClient, target: ConnectionState, timeout: Duration = 5.seconds ) { diff --git a/uts/src/main/kotlin/io/ably/pubsub/uts/infra/integration/AblyJwt.kt b/uts/src/main/kotlin/io/ably/pubsub/uts/infra/integration/AblyJwt.kt new file mode 100644 index 000000000..ef1ae57b2 --- /dev/null +++ b/uts/src/main/kotlin/io/ably/pubsub/uts/infra/integration/AblyJwt.kt @@ -0,0 +1,49 @@ +package io.ably.pubsub.uts.infra.integration + +import java.util.Base64 +import javax.crypto.Mac +import javax.crypto.spec.SecretKeySpec + +/** + * Minimal HS256 Ably JWT signer, built on JDK crypto only (no external JWT library). + * + * Exists for tests that need token claims the native Ably token format cannot carry — + * notably `x-ably-clientType=server`: on token auth the realtime service accepts a + * server-side declaration only from that signed claim (a `-server` agent entry alone is + * rejected with error 40167), and the native token format cannot carry the claim yet. So a + * JWT is the one way a token-authenticated client can declare the server side, which lets + * JWT-based tests run on the server UTS leg. (Native-token tests instead keep their + * token-consuming client on the core constructors, modelling the device the token was minted + * for — see TokenRequestTest.) + */ +object AblyJwt { + /** + * Signs a JWT with the given Ably API key (`keyName:keySecret`), valid for [ttlSeconds], + * with wildcard capability, and the optional Ably claims. + */ + fun sign( + keyStr: String, + clientId: String? = null, + clientType: String? = null, + ttlSeconds: Long = 3600, + ): String { + val keyName = keyStr.substringBefore(':') + val keySecret = keyStr.substringAfter(':') + val now = System.currentTimeMillis() / 1000 + val header = """{"typ":"JWT","alg":"HS256","kid":"$keyName"}""" + val claims = buildString { + append("""{"iat":$now,"exp":${now + ttlSeconds},"x-ably-capability":"{\"*\":[\"*\"]}"""") + if (clientId != null) append(""","x-ably-clientId":"$clientId"""") + if (clientType != null) append(""","x-ably-clientType":"$clientType"""") + append("}") + } + val enc = Base64.getUrlEncoder().withoutPadding() + val signingInput = enc.encodeToString(header.toByteArray(Charsets.UTF_8)) + "." + + enc.encodeToString(claims.toByteArray(Charsets.UTF_8)) + val mac = Mac.getInstance("HmacSHA256").apply { + init(SecretKeySpec(keySecret.toByteArray(Charsets.UTF_8), "HmacSHA256")) + } + val signature = enc.encodeToString(mac.doFinal(signingInput.toByteArray(Charsets.UTF_8))) + return "$signingInput.$signature" + } +} diff --git a/uts/src/main/kotlin/io/ably/lib/uts/infra/integration/SandboxApp.kt b/uts/src/main/kotlin/io/ably/pubsub/uts/infra/integration/SandboxApp.kt similarity index 91% rename from uts/src/main/kotlin/io/ably/lib/uts/infra/integration/SandboxApp.kt rename to uts/src/main/kotlin/io/ably/pubsub/uts/infra/integration/SandboxApp.kt index 45cdb9b51..0752f663e 100644 --- a/uts/src/main/kotlin/io/ably/lib/uts/infra/integration/SandboxApp.kt +++ b/uts/src/main/kotlin/io/ably/pubsub/uts/infra/integration/SandboxApp.kt @@ -1,4 +1,4 @@ -package io.ably.lib.uts.infra.integration +package io.ably.pubsub.uts.infra.integration import com.google.gson.JsonElement import com.google.gson.JsonParser @@ -68,10 +68,13 @@ class SandboxApp private constructor( companion object { /** - * The Ably **nonprod sandbox** host — the `nonprod:sandbox` endpoint (used uniformly across the - * realtime/objects/rest integration specs), resolved to a hostname. Realtime and REST share this - * single host, so point both transports at it: set `realtimeHost` and/or `restHost` from here. + * The Ably **nonprod sandbox** endpoint, used uniformly across the realtime/objects/rest + * integration specs. Set it as the client's `endpoint`; realtime and REST share the host it + * resolves to ([sandboxHost]). */ + const val sandboxEndpoint = "nonprod:sandbox" + + /** The hostname [sandboxEndpoint] resolves to, for direct HTTP calls. */ const val sandboxHost = "sandbox.realtime.ably-nonprod.net" private const val sandboxBaseUrl = "https://$sandboxHost" diff --git a/uts/src/main/kotlin/io/ably/lib/uts/infra/integration/proxy/ProxyManager.kt b/uts/src/main/kotlin/io/ably/pubsub/uts/infra/integration/proxy/ProxyManager.kt similarity index 99% rename from uts/src/main/kotlin/io/ably/lib/uts/infra/integration/proxy/ProxyManager.kt rename to uts/src/main/kotlin/io/ably/pubsub/uts/infra/integration/proxy/ProxyManager.kt index ac344c760..040f4d542 100644 --- a/uts/src/main/kotlin/io/ably/lib/uts/infra/integration/proxy/ProxyManager.kt +++ b/uts/src/main/kotlin/io/ably/pubsub/uts/infra/integration/proxy/ProxyManager.kt @@ -1,4 +1,4 @@ -package io.ably.lib.uts.infra.integration.proxy +package io.ably.pubsub.uts.infra.integration.proxy import io.ktor.client.HttpClient import io.ktor.client.call.body diff --git a/uts/src/main/kotlin/io/ably/lib/uts/infra/integration/proxy/ProxySession.kt b/uts/src/main/kotlin/io/ably/pubsub/uts/infra/integration/proxy/ProxySession.kt similarity index 93% rename from uts/src/main/kotlin/io/ably/lib/uts/infra/integration/proxy/ProxySession.kt rename to uts/src/main/kotlin/io/ably/pubsub/uts/infra/integration/proxy/ProxySession.kt index bf4895956..7928590a9 100644 --- a/uts/src/main/kotlin/io/ably/lib/uts/infra/integration/proxy/ProxySession.kt +++ b/uts/src/main/kotlin/io/ably/pubsub/uts/infra/integration/proxy/ProxySession.kt @@ -1,10 +1,11 @@ -package io.ably.lib.uts.infra.integration.proxy +package io.ably.pubsub.uts.infra.integration.proxy import com.google.gson.Gson import com.google.gson.JsonObject import com.google.gson.reflect.TypeToken -import io.ably.lib.uts.infra.integration.SandboxApp -import io.ably.lib.uts.infra.unit.ClientOptionsBuilder +import io.ably.pubsub.transport.Defaults +import io.ably.pubsub.uts.infra.integration.SandboxApp +import io.ably.pubsub.uts.infra.unit.ClientOptionsBuilder import io.ktor.client.HttpClient import io.ktor.client.engine.cio.CIO import io.ktor.client.plugins.HttpTimeout @@ -214,20 +215,20 @@ class ProxySession private constructor( * @param rules Initial rule set applied to all traffic through this session. * @param port Specific port to listen on; `0` (default) lets the proxy choose. * @param timeoutMs Session idle-timeout in ms; `null` uses the proxy default (30 000 ms). - * @param realtimeHost Upstream Ably realtime host (defaults to sandbox). - * @param restHost Upstream Ably REST host (defaults to sandbox). + * @param endpoint Upstream Ably endpoint (defaults to sandbox). Realtime and REST share the + * host it resolves to (REC1), so the proxy targets that host for both. */ suspend fun create( rules: List = emptyList(), port: Int = 0, timeoutMs: Long? = null, - realtimeHost: String = SandboxApp.sandboxHost, - restHost: String = SandboxApp.sandboxHost, + endpoint: String = SandboxApp.sandboxEndpoint, ): ProxySession { + val upstreamHost = Defaults.getPrimaryDomain(endpoint) val body = JsonObject().apply { add("target", JsonObject().apply { - addProperty("realtimeHost", realtimeHost) - addProperty("restHost", restHost) + addProperty("realtimeHost", upstreamHost) + addProperty("restHost", upstreamHost) }) add("rules", gson.toJsonTree(rules)) if (port != 0) addProperty("port", port) @@ -333,7 +334,7 @@ class ProxySession private constructor( // ── Client wiring ─────────────────────────────────────────────────────────────── /** - * Routes a [TestRealtimeClient] / [TestRestClient] through the given proxy [session]. + * Routes a [TestRealtimeClient] / [TestHttpClient] through the given proxy [session]. * * Call this inside the client builder block to point both the realtime and REST hosts at the * proxy listening on `localhost`: @@ -346,15 +347,14 @@ class ProxySession private constructor( * } * ``` * - * Sets `realtimeHost` and `restHost` to the proxy host, `port` to the session's assigned port, + * Sets `endpoint` to the proxy host, `port` to the session's assigned port, * and `tls = false` (the proxy serves plain HTTP/WS; TLS is only used upstream to the sandbox). * `useBinaryProtocol` is already `false` by default in [ClientOptionsBuilder]. * - * Setting explicit hosts disables fallback hosts automatically, so no `fallbackHosts` is needed. + * A hostname endpoint has no default fallback hosts (REC2c2), so no `fallbackHosts` is needed. */ fun ClientOptionsBuilder.connectThroughProxy(session: ProxySession) { - realtimeHost = session.proxyHost - restHost = session.proxyHost + endpoint = session.proxyHost port = session.proxyPort tls = false } diff --git a/uts/src/main/kotlin/io/ably/pubsub/uts/infra/unit/ClientFactories.kt b/uts/src/main/kotlin/io/ably/pubsub/uts/infra/unit/ClientFactories.kt new file mode 100644 index 000000000..242be969c --- /dev/null +++ b/uts/src/main/kotlin/io/ably/pubsub/uts/infra/unit/ClientFactories.kt @@ -0,0 +1,59 @@ +package io.ably.pubsub.uts.infra.unit + +import io.ably.pubsub.debug.DebugOptions +import io.ably.pubsub.realtime.PubSubRealtimeClient +import io.ably.pubsub.realtime.RealtimeClientFactory +import io.ably.pubsub.http.HttpClientFactory +import io.ably.pubsub.http.PubSubHttpClient +import io.ably.pubsub.server.PubSubServer + +class ClientOptionsBuilder : DebugOptions("appId.keyId:keySecret") { + init { + useBinaryProtocol = false + } + + fun install(mock: MockWebSocket) = mock.installOn(this) + fun install(mock: MockHttpClient) = mock.installOn(this) + + fun enableFakeTimers(fakeClock: FakeClock) { + clock = fakeClock + } +} + +/** + * Which package's entry points the suite constructs clients through, selected by the + * `uts.side` system property (uts/build.gradle.kts forwards it to the test JVM): + * + * - `core` (default): the core construction seam ([RealtimeClientFactory] / [HttpClientFactory]), + * which declares no side. + * - `server`: `io.ably.pubsub:server` — both client kinds via its side-stamping builders. + * + * There is no `device` mode, unlike ably-js's UTS: `io.ably.pubsub:device` is an Android + * artifact, so its door cannot run on the JVM this suite uses; its stamping contract is + * covered by the instrumentation tests in the device module instead. + * + * The builders only stamp the side-declaring agent entry and pass every other option + * through — [DebugOptions] included: its `copy()` override keeps the mock hooks the suite + * installs — so conformance must be identical whichever door constructed the client. + * `SideModesTest` asserts each mode's stamp, so a broken seam cannot silently degrade the + * server CI leg into a duplicate of the core leg. + */ +val utsSide: String = System.getProperty("uts.side").let { if (it.isNullOrEmpty()) "core" else it } + +fun TestRealtimeClient(block: ClientOptionsBuilder.() -> Unit): PubSubRealtimeClient { + val options = ClientOptionsBuilder().apply(block) + return when (utsSide) { + "core" -> RealtimeClientFactory.create(options) + "server" -> PubSubServer.realtimeClientBuilder(options).build() + else -> throw IllegalArgumentException("Unknown uts.side '$utsSide': use 'core' or 'server'") + } +} + +fun TestHttpClient(block: ClientOptionsBuilder.() -> Unit): PubSubHttpClient { + val options = ClientOptionsBuilder().apply(block) + return when (utsSide) { + "core" -> HttpClientFactory.create(options) + "server" -> PubSubServer.httpClientBuilder(options).build() + else -> throw IllegalArgumentException("Unknown uts.side '$utsSide': use 'core' or 'server'") + } +} diff --git a/uts/src/main/kotlin/io/ably/lib/uts/infra/unit/DefaultPendingConnection.kt b/uts/src/main/kotlin/io/ably/pubsub/uts/infra/unit/DefaultPendingConnection.kt similarity index 90% rename from uts/src/main/kotlin/io/ably/lib/uts/infra/unit/DefaultPendingConnection.kt rename to uts/src/main/kotlin/io/ably/pubsub/uts/infra/unit/DefaultPendingConnection.kt index ba7f0470b..26cc83294 100644 --- a/uts/src/main/kotlin/io/ably/lib/uts/infra/unit/DefaultPendingConnection.kt +++ b/uts/src/main/kotlin/io/ably/pubsub/uts/infra/unit/DefaultPendingConnection.kt @@ -1,8 +1,8 @@ -package io.ably.lib.uts.infra.unit +package io.ably.pubsub.uts.infra.unit -import io.ably.lib.network.WebSocketListener -import io.ably.lib.types.ProtocolMessage -import io.ably.lib.util.Serialisation +import io.ably.pubsub.network.WebSocketListener +import io.ably.pubsub.types.ProtocolMessage +import io.ably.pubsub.util.Serialisation import java.io.IOException import java.net.SocketTimeoutException import java.net.UnknownHostException diff --git a/uts/src/main/kotlin/io/ably/lib/uts/infra/unit/DefaultPendingRequest.kt b/uts/src/main/kotlin/io/ably/pubsub/uts/infra/unit/DefaultPendingRequest.kt similarity index 87% rename from uts/src/main/kotlin/io/ably/lib/uts/infra/unit/DefaultPendingRequest.kt rename to uts/src/main/kotlin/io/ably/pubsub/uts/infra/unit/DefaultPendingRequest.kt index 4eb6f48c7..828040162 100644 --- a/uts/src/main/kotlin/io/ably/lib/uts/infra/unit/DefaultPendingRequest.kt +++ b/uts/src/main/kotlin/io/ably/pubsub/uts/infra/unit/DefaultPendingRequest.kt @@ -1,10 +1,10 @@ -package io.ably.lib.uts.infra.unit +package io.ably.pubsub.uts.infra.unit -import io.ably.lib.network.FailedConnectionException -import io.ably.lib.network.HttpBody -import io.ably.lib.network.HttpRequest -import io.ably.lib.network.HttpResponse -import io.ably.lib.util.Serialisation +import io.ably.pubsub.network.FailedConnectionException +import io.ably.pubsub.network.HttpBody +import io.ably.pubsub.network.HttpRequest +import io.ably.pubsub.network.HttpResponse +import io.ably.pubsub.util.Serialisation import kotlin.time.Duration import kotlinx.coroutines.CompletableDeferred import java.net.SocketTimeoutException diff --git a/uts/src/main/kotlin/io/ably/lib/uts/infra/unit/FakeClock.kt b/uts/src/main/kotlin/io/ably/pubsub/uts/infra/unit/FakeClock.kt similarity index 96% rename from uts/src/main/kotlin/io/ably/lib/uts/infra/unit/FakeClock.kt rename to uts/src/main/kotlin/io/ably/pubsub/uts/infra/unit/FakeClock.kt index 8527c836c..62eda6e45 100644 --- a/uts/src/main/kotlin/io/ably/lib/uts/infra/unit/FakeClock.kt +++ b/uts/src/main/kotlin/io/ably/pubsub/uts/infra/unit/FakeClock.kt @@ -1,8 +1,8 @@ -package io.ably.lib.uts.infra.unit +package io.ably.pubsub.uts.infra.unit -import io.ably.lib.util.Clock -import io.ably.lib.util.AblyTimer -import io.ably.lib.util.TimerInstance +import io.ably.pubsub.util.Clock +import io.ably.pubsub.util.AblyTimer +import io.ably.pubsub.util.TimerInstance import java.util.TimerTask import java.util.concurrent.ConcurrentHashMap import kotlin.time.Duration @@ -10,7 +10,7 @@ import kotlin.time.Duration /** * Virtual clock for deterministic time control in unit tests. * - * Install via `enableFakeTimers(fakeClock)` inside a `TestRealtimeClient` or `TestRestClient` block. + * Install via `enableFakeTimers(fakeClock)` inside a `TestRealtimeClient` or `TestHttpClient` block. * Time only advances when [advance] is called; timer callbacks fire synchronously within that call. */ class FakeClock(initialTimeMs: Long = 0L) : Clock { diff --git a/uts/src/main/kotlin/io/ably/lib/uts/infra/unit/MockEvent.kt b/uts/src/main/kotlin/io/ably/pubsub/uts/infra/unit/MockEvent.kt similarity index 95% rename from uts/src/main/kotlin/io/ably/lib/uts/infra/unit/MockEvent.kt rename to uts/src/main/kotlin/io/ably/pubsub/uts/infra/unit/MockEvent.kt index 99fea4195..a1804ad8d 100644 --- a/uts/src/main/kotlin/io/ably/lib/uts/infra/unit/MockEvent.kt +++ b/uts/src/main/kotlin/io/ably/pubsub/uts/infra/unit/MockEvent.kt @@ -1,6 +1,6 @@ -package io.ably.lib.uts.infra.unit +package io.ably.pubsub.uts.infra.unit -import io.ably.lib.types.ProtocolMessage +import io.ably.pubsub.types.ProtocolMessage import java.net.URL /** Ordered log of everything that happened on a mock transport. Inspect via [MockWebSocket.events]. */ diff --git a/uts/src/main/kotlin/io/ably/lib/uts/infra/unit/MockHttpClient.kt b/uts/src/main/kotlin/io/ably/pubsub/uts/infra/unit/MockHttpClient.kt similarity index 94% rename from uts/src/main/kotlin/io/ably/lib/uts/infra/unit/MockHttpClient.kt rename to uts/src/main/kotlin/io/ably/pubsub/uts/infra/unit/MockHttpClient.kt index 7f498710a..52fc45a49 100644 --- a/uts/src/main/kotlin/io/ably/lib/uts/infra/unit/MockHttpClient.kt +++ b/uts/src/main/kotlin/io/ably/pubsub/uts/infra/unit/MockHttpClient.kt @@ -1,7 +1,7 @@ -package io.ably.lib.uts.infra.unit +package io.ably.pubsub.uts.infra.unit -import io.ably.lib.debug.DebugOptions -import io.ably.lib.network.HttpEngine +import io.ably.pubsub.debug.DebugOptions +import io.ably.pubsub.network.HttpEngine import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.withContext @@ -23,7 +23,7 @@ class HttpMockConfig { } /** - * Fake HTTP engine for SDK unit tests. Install via [installOn] or `TestRestClient`/`TestRealtimeClient`. + * Fake HTTP engine for SDK unit tests. Install via [installOn] or `TestHttpClient`/`TestRealtimeClient`. */ class MockHttpClient(private val config: HttpMockConfig = HttpMockConfig()) { @Volatile private var _pendingConnections = Channel(Channel.UNLIMITED) diff --git a/uts/src/main/kotlin/io/ably/lib/uts/infra/unit/MockHttpEngine.kt b/uts/src/main/kotlin/io/ably/pubsub/uts/infra/unit/MockHttpEngine.kt similarity index 86% rename from uts/src/main/kotlin/io/ably/lib/uts/infra/unit/MockHttpEngine.kt rename to uts/src/main/kotlin/io/ably/pubsub/uts/infra/unit/MockHttpEngine.kt index dfe159ded..48e96e43d 100644 --- a/uts/src/main/kotlin/io/ably/lib/uts/infra/unit/MockHttpEngine.kt +++ b/uts/src/main/kotlin/io/ably/pubsub/uts/infra/unit/MockHttpEngine.kt @@ -1,11 +1,11 @@ -package io.ably.lib.uts.infra.unit +package io.ably.pubsub.uts.infra.unit -import io.ably.lib.network.FailedConnectionException -import io.ably.lib.network.HttpCall -import io.ably.lib.network.HttpEngine -import io.ably.lib.network.HttpRequest -import io.ably.lib.network.HttpResponse -import io.ably.lib.types.ProtocolMessage +import io.ably.pubsub.network.FailedConnectionException +import io.ably.pubsub.network.HttpCall +import io.ably.pubsub.network.HttpEngine +import io.ably.pubsub.network.HttpRequest +import io.ably.pubsub.network.HttpResponse +import io.ably.pubsub.types.ProtocolMessage import kotlinx.coroutines.CompletableDeferred import kotlinx.coroutines.runBlocking import java.io.IOException @@ -40,7 +40,7 @@ internal class MockHttpCall( // Phase 2 — request val rd = CompletableDeferred().also { respDeferred = it } - onRequest(io.ably.lib.uts.infra.unit.DefaultPendingRequest(request, rd)) + onRequest(io.ably.pubsub.uts.infra.unit.DefaultPendingRequest(request, rd)) rd.await() } diff --git a/uts/src/main/kotlin/io/ably/lib/uts/infra/unit/MockWebSocket.kt b/uts/src/main/kotlin/io/ably/pubsub/uts/infra/unit/MockWebSocket.kt similarity index 96% rename from uts/src/main/kotlin/io/ably/lib/uts/infra/unit/MockWebSocket.kt rename to uts/src/main/kotlin/io/ably/pubsub/uts/infra/unit/MockWebSocket.kt index 6489a5bf5..fad0ad4f1 100644 --- a/uts/src/main/kotlin/io/ably/lib/uts/infra/unit/MockWebSocket.kt +++ b/uts/src/main/kotlin/io/ably/pubsub/uts/infra/unit/MockWebSocket.kt @@ -1,11 +1,11 @@ -package io.ably.lib.uts.infra.unit - -import io.ably.lib.debug.DebugOptions -import io.ably.lib.network.WebSocketEngineFactory -import io.ably.lib.network.WebSocketListener -import io.ably.lib.types.ProtocolMessage -import io.ably.lib.types.ProtocolSerializer -import io.ably.lib.util.Serialisation +package io.ably.pubsub.uts.infra.unit + +import io.ably.pubsub.debug.DebugOptions +import io.ably.pubsub.network.WebSocketEngineFactory +import io.ably.pubsub.network.WebSocketListener +import io.ably.pubsub.types.ProtocolMessage +import io.ably.pubsub.types.ProtocolSerializer +import io.ably.pubsub.util.Serialisation import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.withContext diff --git a/uts/src/main/kotlin/io/ably/lib/uts/infra/unit/MockWebSocketEngineFactory.kt b/uts/src/main/kotlin/io/ably/pubsub/uts/infra/unit/MockWebSocketEngineFactory.kt similarity index 88% rename from uts/src/main/kotlin/io/ably/lib/uts/infra/unit/MockWebSocketEngineFactory.kt rename to uts/src/main/kotlin/io/ably/pubsub/uts/infra/unit/MockWebSocketEngineFactory.kt index 28513e455..4239280eb 100644 --- a/uts/src/main/kotlin/io/ably/lib/uts/infra/unit/MockWebSocketEngineFactory.kt +++ b/uts/src/main/kotlin/io/ably/pubsub/uts/infra/unit/MockWebSocketEngineFactory.kt @@ -1,11 +1,11 @@ -package io.ably.lib.uts.infra.unit +package io.ably.pubsub.uts.infra.unit -import io.ably.lib.network.EngineType -import io.ably.lib.network.WebSocketClient -import io.ably.lib.network.WebSocketEngine -import io.ably.lib.network.WebSocketEngineConfig -import io.ably.lib.network.WebSocketEngineFactory -import io.ably.lib.network.WebSocketListener +import io.ably.pubsub.network.EngineType +import io.ably.pubsub.network.WebSocketClient +import io.ably.pubsub.network.WebSocketEngine +import io.ably.pubsub.network.WebSocketEngineConfig +import io.ably.pubsub.network.WebSocketEngineFactory +import io.ably.pubsub.network.WebSocketListener import java.net.URI internal class MockWebSocketEngineFactory( diff --git a/uts/src/main/kotlin/io/ably/lib/uts/infra/unit/PendingConnection.kt b/uts/src/main/kotlin/io/ably/pubsub/uts/infra/unit/PendingConnection.kt similarity index 93% rename from uts/src/main/kotlin/io/ably/lib/uts/infra/unit/PendingConnection.kt rename to uts/src/main/kotlin/io/ably/pubsub/uts/infra/unit/PendingConnection.kt index 588f9759d..1c4bb4f86 100644 --- a/uts/src/main/kotlin/io/ably/lib/uts/infra/unit/PendingConnection.kt +++ b/uts/src/main/kotlin/io/ably/pubsub/uts/infra/unit/PendingConnection.kt @@ -1,6 +1,6 @@ -package io.ably.lib.uts.infra.unit +package io.ably.pubsub.uts.infra.unit -import io.ably.lib.types.ProtocolMessage +import io.ably.pubsub.types.ProtocolMessage import java.net.URLDecoder internal fun parseQueryString(rawQuery: String?): Map { diff --git a/uts/src/main/kotlin/io/ably/lib/uts/infra/unit/PendingRequest.kt b/uts/src/main/kotlin/io/ably/pubsub/uts/infra/unit/PendingRequest.kt similarity index 94% rename from uts/src/main/kotlin/io/ably/lib/uts/infra/unit/PendingRequest.kt rename to uts/src/main/kotlin/io/ably/pubsub/uts/infra/unit/PendingRequest.kt index 43d28ff4b..92cd1351f 100644 --- a/uts/src/main/kotlin/io/ably/lib/uts/infra/unit/PendingRequest.kt +++ b/uts/src/main/kotlin/io/ably/pubsub/uts/infra/unit/PendingRequest.kt @@ -1,4 +1,4 @@ -package io.ably.lib.uts.infra.unit +package io.ably.pubsub.uts.infra.unit import java.net.URL import kotlin.time.Duration diff --git a/uts/src/main/kotlin/io/ably/lib/uts/infra/unit/Utils.kt b/uts/src/main/kotlin/io/ably/pubsub/uts/infra/unit/Utils.kt similarity index 86% rename from uts/src/main/kotlin/io/ably/lib/uts/infra/unit/Utils.kt rename to uts/src/main/kotlin/io/ably/pubsub/uts/infra/unit/Utils.kt index 34527348f..c44e73a39 100644 --- a/uts/src/main/kotlin/io/ably/lib/uts/infra/unit/Utils.kt +++ b/uts/src/main/kotlin/io/ably/pubsub/uts/infra/unit/Utils.kt @@ -1,12 +1,12 @@ -package io.ably.lib.uts.infra.unit +package io.ably.pubsub.uts.infra.unit -import io.ably.lib.types.ConnectionDetails +import io.ably.pubsub.types.ConnectionDetails /** * Test-only builder DSL for [ConnectionDetails], e.g. * `ConnectionDetails { connectionKey = "key-1"; connectionStateTtl = 120_000L }`. * - * [ConnectionDetails]'s no-arg constructor is package-private to `io.ably.lib.types`, so it cannot be + * [ConnectionDetails]'s no-arg constructor is package-private to `io.ably.pubsub.types`, so it cannot be * invoked directly from this package. We obtain an instance reflectively via [newConnectionDetails] — * the same package-private-access technique used by `liveobjects/.../TestUtils.kt`. */ diff --git a/uts/src/test/kotlin/io/ably/lib/uts/integration/proxy/ProxyInfraSmokeTest.kt b/uts/src/test/kotlin/io/ably/pubsub/uts/integration/proxy/ProxyInfraSmokeTest.kt similarity index 77% rename from uts/src/test/kotlin/io/ably/lib/uts/integration/proxy/ProxyInfraSmokeTest.kt rename to uts/src/test/kotlin/io/ably/pubsub/uts/integration/proxy/ProxyInfraSmokeTest.kt index ccb0aef82..b82c6c17d 100644 --- a/uts/src/test/kotlin/io/ably/lib/uts/integration/proxy/ProxyInfraSmokeTest.kt +++ b/uts/src/test/kotlin/io/ably/pubsub/uts/integration/proxy/ProxyInfraSmokeTest.kt @@ -1,18 +1,20 @@ -package io.ably.lib.uts.integration.proxy - -import io.ably.lib.realtime.ChannelState -import io.ably.lib.realtime.ConnectionState -import io.ably.lib.rest.AblyRest -import io.ably.lib.rest.Auth -import io.ably.lib.uts.infra.awaitChannelState -import io.ably.lib.uts.infra.awaitState -import io.ably.lib.uts.infra.integration.SandboxApp -import io.ably.lib.uts.infra.integration.proxy.ProxyManager -import io.ably.lib.uts.infra.integration.proxy.ProxySession -import io.ably.lib.uts.infra.integration.proxy.connectThroughProxy -import io.ably.lib.uts.infra.integration.proxy.wsFrameToClientRule -import io.ably.lib.uts.infra.pollUntil -import io.ably.lib.uts.infra.unit.TestRealtimeClient +package io.ably.pubsub.uts.integration.proxy + +import io.ably.pubsub.realtime.ChannelState +import io.ably.pubsub.realtime.ConnectionState +import io.ably.pubsub.http.Auth +import io.ably.pubsub.types.ClientOptions +import io.ably.pubsub.uts.infra.awaitChannelState +import io.ably.pubsub.uts.infra.awaitState +import io.ably.pubsub.uts.infra.integration.AblyJwt +import io.ably.pubsub.uts.infra.integration.SandboxApp +import io.ably.pubsub.uts.infra.integration.proxy.ProxyManager +import io.ably.pubsub.uts.infra.integration.proxy.ProxySession +import io.ably.pubsub.uts.infra.integration.proxy.connectThroughProxy +import io.ably.pubsub.uts.infra.integration.proxy.wsFrameToClientRule +import io.ably.pubsub.uts.infra.pollUntil +import io.ably.pubsub.uts.infra.unit.TestRealtimeClient +import io.ably.pubsub.uts.infra.unit.utsSide import kotlinx.coroutines.runBlocking import kotlinx.coroutines.test.runTest import org.junit.jupiter.api.AfterAll @@ -22,7 +24,6 @@ import org.junit.jupiter.api.TestInstance import java.util.Collections import java.util.UUID import java.util.concurrent.atomic.AtomicInteger -import kotlin.test.assertEquals import kotlin.test.assertNotNull import kotlin.test.assertTrue import kotlin.time.Duration.Companion.seconds @@ -71,14 +72,20 @@ class ProxyInfraSmokeTest { val session = ProxySession.create(rules = emptyList()) assertTrue(session.proxyPort > 0) - val tokenSigner = AblyRest(app.defaultKey) val authCallbackCount = AtomicInteger(0) val client = TestRealtimeClient { // Basic key auth is TLS-only, so authenticate through the proxy with a locally-signed - // TokenRequest (README §11 teaching point). + // token (README §11 teaching point). It is a JWT rather than a native TokenRequest + // because only a JWT can carry the x-ably-clientType claim: on token auth realtime + // accepts a server-side declaration from that signed claim alone, rejecting the bare + // agent entry the server leg's door stamps with 40167. authCallback = Auth.TokenCallback { params -> authCallbackCount.incrementAndGet() - tokenSigner.auth.createTokenRequest(params, null) + AblyJwt.sign( + app.defaultKey, + clientId = params.clientId, + clientType = if (utsSide == "server") "server" else null, + ) } connectThroughProxy(session) autoConnect = false @@ -116,7 +123,6 @@ class ProxyInfraSmokeTest { client.close() } finally { session.close() - runCatching { tokenSigner.close() } } } } @@ -134,10 +140,14 @@ class ProxyInfraSmokeTest { ), ) - val tokenSigner = AblyRest(app.defaultKey) val client = TestRealtimeClient { + // A claim-bearing JWT, for the reason given in the first test. authCallback = Auth.TokenCallback { params -> - tokenSigner.auth.createTokenRequest(params, null) + AblyJwt.sign( + app.defaultKey, + clientId = params.clientId, + clientType = if (utsSide == "server") "server" else null, + ) } connectThroughProxy(session) autoConnect = false @@ -164,7 +174,6 @@ class ProxyInfraSmokeTest { client.close() } finally { session.close() - runCatching { tokenSigner.close() } } } } diff --git a/uts/src/test/kotlin/io/ably/lib/uts/integration/standard/IntegrationInfraSmokeTest.kt b/uts/src/test/kotlin/io/ably/pubsub/uts/integration/standard/IntegrationInfraSmokeTest.kt similarity index 81% rename from uts/src/test/kotlin/io/ably/lib/uts/integration/standard/IntegrationInfraSmokeTest.kt rename to uts/src/test/kotlin/io/ably/pubsub/uts/integration/standard/IntegrationInfraSmokeTest.kt index 166d913c3..95c2d03ce 100644 --- a/uts/src/test/kotlin/io/ably/lib/uts/integration/standard/IntegrationInfraSmokeTest.kt +++ b/uts/src/test/kotlin/io/ably/pubsub/uts/integration/standard/IntegrationInfraSmokeTest.kt @@ -1,22 +1,22 @@ -package io.ably.lib.uts.integration.standard - -import io.ably.lib.realtime.AblyRealtime -import io.ably.lib.realtime.Channel -import io.ably.lib.realtime.ChannelState -import io.ably.lib.realtime.ConnectionState -import io.ably.lib.rest.AblyRest -import io.ably.lib.types.AblyException -import io.ably.lib.types.Callback -import io.ably.lib.types.ErrorInfo -import io.ably.lib.types.Message -import io.ably.lib.types.PaginatedResult -import io.ably.lib.types.PublishResult -import io.ably.lib.uts.infra.awaitChannelState -import io.ably.lib.uts.infra.awaitState -import io.ably.lib.uts.infra.integration.SandboxApp -import io.ably.lib.uts.infra.pollUntil -import io.ably.lib.uts.infra.unit.TestRealtimeClient -import io.ably.lib.uts.infra.unit.TestRestClient +package io.ably.pubsub.uts.integration.standard + +import io.ably.pubsub.realtime.PubSubRealtimeClient +import io.ably.pubsub.realtime.Channel +import io.ably.pubsub.realtime.ChannelState +import io.ably.pubsub.realtime.ConnectionState +import io.ably.pubsub.http.PubSubHttpClient +import io.ably.pubsub.types.AblyException +import io.ably.pubsub.types.Callback +import io.ably.pubsub.types.ErrorInfo +import io.ably.pubsub.types.Message +import io.ably.pubsub.types.PaginatedResult +import io.ably.pubsub.types.PublishResult +import io.ably.pubsub.uts.infra.awaitChannelState +import io.ably.pubsub.uts.infra.awaitState +import io.ably.pubsub.uts.infra.integration.SandboxApp +import io.ably.pubsub.uts.infra.pollUntil +import io.ably.pubsub.uts.infra.unit.TestRealtimeClient +import io.ably.pubsub.uts.infra.unit.TestHttpClient import kotlinx.coroutines.runBlocking import kotlinx.coroutines.suspendCancellableCoroutine import kotlinx.coroutines.test.runTest @@ -36,7 +36,7 @@ import kotlin.time.Duration.Companion.seconds /** * Acceptance test for the **direct-sandbox integration infrastructure itself** ([SandboxApp] + - * [TestRealtimeClient] / [TestRestClient] wired straight to the sandbox) — this is + * [TestRealtimeClient] / [TestHttpClient] wired straight to the sandbox) — this is * NOT derived from a UTS spec, so it carries no `@UTS` marker. It is the permanent teaching example * for `uts/README.md` §10 and the reference shape a future integration-tier UTS test should take. * @@ -75,7 +75,7 @@ class IntegrationInfraSmokeTest { val channelName = "smoke-int-${UUID.randomUUID()}" val client = newRealtimeClient(useBinaryProtocol) - val rest = newRestClient(useBinaryProtocol) + val rest = newHttpClient(useBinaryProtocol) try { // State-transition sequence, not just the final state: collect before connect. val states = Collections.synchronizedList(mutableListOf()) @@ -126,18 +126,17 @@ class IntegrationInfraSmokeTest { // ── helpers ────────────────────────────────────────────────────────────── /** A realtime client wired straight to the nonprod sandbox (no proxy). */ - private fun newRealtimeClient(useBinaryProtocol: Boolean): AblyRealtime = TestRealtimeClient { + private fun newRealtimeClient(useBinaryProtocol: Boolean): PubSubRealtimeClient = TestRealtimeClient { key = app.defaultKey - realtimeHost = SandboxApp.sandboxHost - restHost = SandboxApp.sandboxHost + endpoint = SandboxApp.sandboxEndpoint this.useBinaryProtocol = useBinaryProtocol autoConnect = false } /** A REST client wired straight to the nonprod sandbox (the REST half of the infra). */ - private fun newRestClient(useBinaryProtocol: Boolean): AblyRest = TestRestClient { + private fun newHttpClient(useBinaryProtocol: Boolean): PubSubHttpClient = TestHttpClient { key = app.defaultKey - restHost = SandboxApp.sandboxHost + endpoint = SandboxApp.sandboxEndpoint this.useBinaryProtocol = useBinaryProtocol } diff --git a/uts/src/test/kotlin/io/ably/pubsub/uts/unit/SideModesTest.kt b/uts/src/test/kotlin/io/ably/pubsub/uts/unit/SideModesTest.kt new file mode 100644 index 000000000..f186310d7 --- /dev/null +++ b/uts/src/test/kotlin/io/ably/pubsub/uts/unit/SideModesTest.kt @@ -0,0 +1,106 @@ +package io.ably.pubsub.uts.unit + +/* + * Harness self-test for the uts.side modes — not a UTS spec translation. + * + * The suite can construct its clients through the core constructors or through the server + * door's builders (see the uts.side handling in ClientFactories.kt). The builders' one + * observable behavior is the side-declaring Ably-Agent entry they stamp, so this file + * asserts that the stamp matches the selected mode. It exists to fail loudly if the seam + * silently degrades — for example if a refactor bypasses the factories and a "server" run + * quietly constructs plain core clients, turning the server CI leg into a duplicate of the + * core leg. + * + * The side entry is registered in the ably-common agents registry as a versionless flag — a + * bare token — so the assertions also fail if a `/version` form regresses. Mirrors ably-js's + * side_modes.test.ts. + */ + +import io.ably.pubsub.http.PubSubBase +import io.ably.pubsub.util.Side +import io.ably.pubsub.uts.infra.unit.MockHttpClient +import io.ably.pubsub.uts.infra.unit.TestRealtimeClient +import io.ably.pubsub.uts.infra.unit.TestHttpClient +import io.ably.pubsub.uts.infra.unit.utsSide +import kotlin.test.Test +import kotlin.test.assertFalse +import kotlin.test.assertNotNull +import kotlin.test.assertTrue +import org.junit.jupiter.api.Timeout + +@Timeout(30) +class SideModesTest { + + /** + * Builds a client, drives one HTTP request through the mock engine, and returns the + * Ably-Agent header it carried. The response body is irrelevant — only the captured + * request headers matter — so any parse failure in the SDK is swallowed. + */ + private fun agentHeaderFrom(makeClient: (MockHttpClient) -> PubSubBase): String { + val captured = mutableListOf>>() + val mock = MockHttpClient { + onConnectionAttempt = { it.respondWithSuccess() } + onRequest = { request -> + captured += request.headers + request.respondWith(200, "[1704067200000]") + } + } + val client = makeClient(mock) + try { + runCatching { client.time() } + } finally { + runCatching { client.close() } + } + + assertTrue(captured.isNotEmpty(), "expected the mock engine to observe a request") + val agent = captured.first().entries + .firstOrNull { it.key.equals("Ably-Agent", ignoreCase = true) } + ?.value?.firstOrNull() + assertNotNull(agent, "expected an Ably-Agent header, got headers: ${captured.first().keys}") + return agent + } + + /** + * What the selected mode must stamp: nothing for `core`; the bare (versionless) server + * flag for `server` — never the device flag, and never any `ably-pubsub-server/...` form. + */ + private fun assertStamp(agent: String) { + val tokens = agent.split(" ") + // The family identifier (ably-pubsub-java/) shares the ably-pubsub- prefix + // with the side flags, so the side checks match the exact identifiers, never the prefix. + val sideTokens = tokens.filter { + it == Side.DEVICE_AGENT_IDENTIFIER || it == Side.SERVER_AGENT_IDENTIFIER || + it.startsWith(Side.DEVICE_AGENT_IDENTIFIER + "/") || it.startsWith(Side.SERVER_AGENT_IDENTIFIER + "/") + } + when (utsSide) { + "core" -> assertTrue( + sideTokens.isEmpty(), + "core mode must not stamp a side entry, got: $agent", + ) + "server" -> { + assertTrue(tokens.contains(Side.SERVER_AGENT_IDENTIFIER), "expected the bare server side flag in: $agent") + assertFalse(agent.contains(Side.SERVER_AGENT_IDENTIFIER + "/"), "the side flag must be versionless in: $agent") + assertFalse(tokens.any { it.startsWith(Side.DEVICE_AGENT_IDENTIFIER) }, "a server client must not carry the device entry: $agent") + } + else -> throw IllegalArgumentException("Unknown uts.side '$utsSide'") + } + assertTrue(agent.contains("ably-pubsub-java/"), "the family identifier must always be present in: $agent") + } + + @Test + fun `REST clients carry the agent stamp of the selected entry point`() { + assertStamp(agentHeaderFrom { mock -> TestHttpClient { install(mock) } }) + } + + @Test + fun `realtime clients carry the agent stamp of the selected entry point`() { + assertStamp( + agentHeaderFrom { mock -> + TestRealtimeClient { + autoConnect = false + install(mock) + } + }, + ) + } +} diff --git a/uts/src/test/kotlin/io/ably/lib/uts/unit/UnitInfraSmokeTest.kt b/uts/src/test/kotlin/io/ably/pubsub/uts/unit/UnitInfraSmokeTest.kt similarity index 92% rename from uts/src/test/kotlin/io/ably/lib/uts/unit/UnitInfraSmokeTest.kt rename to uts/src/test/kotlin/io/ably/pubsub/uts/unit/UnitInfraSmokeTest.kt index c7b795663..57d9a815e 100644 --- a/uts/src/test/kotlin/io/ably/lib/uts/unit/UnitInfraSmokeTest.kt +++ b/uts/src/test/kotlin/io/ably/pubsub/uts/unit/UnitInfraSmokeTest.kt @@ -1,20 +1,20 @@ -package io.ably.lib.uts.unit +package io.ably.pubsub.uts.unit -import io.ably.lib.realtime.ChannelState -import io.ably.lib.realtime.ConnectionState -import io.ably.lib.realtime.ConnectionStateListener -import io.ably.lib.types.ProtocolMessage -import io.ably.lib.uts.infra.awaitChannelState -import io.ably.lib.uts.infra.awaitState -import io.ably.lib.uts.infra.pollUntil -import io.ably.lib.uts.infra.unit.CONNECTED_MESSAGE -import io.ably.lib.uts.infra.unit.ConnectionDetails -import io.ably.lib.uts.infra.unit.FakeClock -import io.ably.lib.uts.infra.unit.MockEvent -import io.ably.lib.uts.infra.unit.MockHttpClient -import io.ably.lib.uts.infra.unit.MockWebSocket -import io.ably.lib.uts.infra.unit.PendingConnection -import io.ably.lib.uts.infra.unit.TestRealtimeClient +import io.ably.pubsub.realtime.ChannelState +import io.ably.pubsub.realtime.ConnectionState +import io.ably.pubsub.realtime.ConnectionStateListener +import io.ably.pubsub.types.ProtocolMessage +import io.ably.pubsub.uts.infra.awaitChannelState +import io.ably.pubsub.uts.infra.awaitState +import io.ably.pubsub.uts.infra.pollUntil +import io.ably.pubsub.uts.infra.unit.CONNECTED_MESSAGE +import io.ably.pubsub.uts.infra.unit.ConnectionDetails +import io.ably.pubsub.uts.infra.unit.FakeClock +import io.ably.pubsub.uts.infra.unit.MockEvent +import io.ably.pubsub.uts.infra.unit.MockHttpClient +import io.ably.pubsub.uts.infra.unit.MockWebSocket +import io.ably.pubsub.uts.infra.unit.PendingConnection +import io.ably.pubsub.uts.infra.unit.TestRealtimeClient import kotlinx.coroutines.CompletableDeferred import kotlinx.coroutines.launch import kotlinx.coroutines.test.runTest @@ -154,12 +154,12 @@ class UnitInfraSmokeTest { /** * The fake HTTP engine exercised for real via token auth. Uses the **callback style** - * ([io.ably.lib.uts.infra.unit.WebSocketMockConfig.onConnectionAttempt]) for the WebSocket, and + * ([io.ably.pubsub.uts.infra.unit.WebSocketMockConfig.onConnectionAttempt]) for the WebSocket, and * the **await style** ([MockHttpClient.awaitRequest]) for the auth HTTP request. * * Trap: [MockEvent.HttpRequest] is declared but never emitted by the HTTP mock — asserting on * `events.filterIsInstance()` would silently pass on an empty list. We - * assert via [MockHttpClient.awaitRequest] / the [io.ably.lib.uts.infra.unit.PendingRequest] + * assert via [MockHttpClient.awaitRequest] / the [io.ably.pubsub.uts.infra.unit.PendingRequest] * instead. */ @Test