> ## Documentation Index
> Fetch the complete documentation index at: https://docs.tensor9.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Testing Service Adapters

> Test one directed service mapping locally, then verify it inside a representative BYOC test install.

Test a service adapter at two boundaries. First, run one mapping locally so you can exercise the origin API, translated behavior, and native target state without deploying the rest of your application. Then repeat the same contract test inside a BYOC test install so it includes the compiled stack, workload identity, network path, and deployment configuration your customers will use.

These tests answer different questions. A successful local test does not prove that a BYOC deployment is configured correctly, and a healthy deployment does not prove every operation your application uses has equivalent behavior.

## Choose the right test boundary

| Boundary                    | Use it to answer                                                                                  | What it does not prove                                                             |
| --------------------------- | ------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------- |
| Directed profile inspection | Does Tensor9 document this origin service, target service, operation, and limitation?             | Credentials, networking, runtime behavior, or target effects                       |
| Local single-binary adapter | Does one application request reach the selected adapter and produce the expected target behavior? | BYOC compilation, install configuration, customer networking, or workload identity |
| BYOC test install           | Does the released application use the adapter correctly in the selected customer form factor?     | Every production workload shape, quota, scale, or customer-specific policy         |
| Production verification     | Does the approved release behave correctly in one customer install?                               | Compatibility for another customer, target, region, or release                     |

Start with the smallest boundary that can disprove your assumption. Move outward only after the inner test is repeatable.

## Test one mapping locally

The example below tests an application that uses the AWS S3 API while Google Cloud Storage holds the objects. Read the [S3 service-adapter page](/byoc/service-adapters/aws/databases-storage/s3) first and choose an operation that its Google Cloud target profile covers. The shared steps start that one mapping with `tensor9 adapt svc run` in single-binary mode.

```bash theme={null}
export T9_ORIGIN_SERVICE="aws::1.0.0::s3"
export T9_BACKEND_SERVICE="google::1.0.0::gcs"
```

<Steps>
  <Step title="Install or update the Tensor9 CLI">
    Install the customer CLI with Homebrew, then confirm the binary is available:

    ```bash theme={null}
    brew tap tensor9ine/tensor9
    brew install tensor9
    tensor9 --version
    ```

    If `tensor9` is already installed, run `brew upgrade tensor9` instead of the install command.
  </Step>

  <Step title="Confirm the directed service mapping">
    Confirm that you exported the canonical origin and backend service names supplied by this quickstart or guide:

    ```bash theme={null}
    : "${T9_ORIGIN_SERVICE:?set the origin service name shown above}"
    : "${T9_BACKEND_SERVICE:?set the backend service name shown above}"
    printf 'Origin:  %s\nBackend: %s\n' \
      "$T9_ORIGIN_SERVICE" "$T9_BACKEND_SERVICE"
    ```

    Then inspect the mapping before starting a process:

    ```bash theme={null}
    tensor9 explain \
      -origin "$T9_ORIGIN_SERVICE" \
      -target "$T9_BACKEND_SERVICE" \
      -fmt Human
    ```

    Read the supported operations and limitations for that direction. A similarly named service in the target cloud is not enough. If no directed profile exists, choose another mapping before continuing.
  </Step>

  <Step title="Prepare target-cloud access">
    Authenticate with the target cloud using its standard credential chain. The adapter uses that target identity when it calls the backend service.

    Keep credentials in your shell, workload identity, or local credential store. Do not put secrets in the command line, source code, or screenshots.
  </Step>

  <Step title="Start the service adapter">
    Run one service adapter as a foreground process:

    ```bash theme={null}
    tensor9 adapt svc run \
      --origin "$T9_ORIGIN_SERVICE" \
      --backend "$T9_BACKEND_SERVICE"
    ```

    Leave this terminal open. This is single-binary mode: one local process serves one directed service mapping. It does not install a cluster or contact a Tensor9 control plane.
  </Step>

  <Step title="Copy the listening endpoint">
    When the command reports its listening endpoint, copy that exact value into a second terminal:

    ```bash theme={null}
    export T9_CLOUD_ADAPTER_ENDPOINT="<endpoint printed by tensor9>"
    ```

    Keep the endpoint local to the test unless you have deliberately configured network access and authentication for another machine.
  </Step>

  <Step title="Run one bounded request">
    Continue with this page's client or tool instructions. Point only the service under test at `T9_CLOUD_ADAPTER_ENDPOINT`, then perform one operation whose target effect you can verify independently.

    Check both sides: read the origin-shaped response and inspect the native target resource. A successful client response alone does not prove that the target state is correct.
  </Step>

  <Step title="Stop the local adapter">
    Return to the first terminal and press **Control-C**. Confirm the process exits before deleting the test resource with the target cloud's native client.

    If the request failed, preserve the request ID, adapter endpoint, operation name, target request ID, and any `x-t9-explain-*` receipt headers before stopping the process.
  </Step>
</Steps>

The local process uses target-cloud credentials available to your shell. Use a dedicated test project, account, subscription, or namespace with narrowly scoped permissions. Do not reuse a customer's credentials or copy credentials out of a customer environment.

### Point only the service under test at the adapter

For an AWS SDK or the AWS CLI, use the native per-service endpoint setting so unrelated clients keep their normal destinations:

```bash theme={null}
export AWS_ENDPOINT_URL_S3="$T9_CLOUD_ADAPTER_ENDPOINT"
```

You can instead set the endpoint on one client instance. The [Cloud Adapter SDK guides](/cloud-adapter/guides/index) show both patterns for Java, JavaScript, Python, Go, .NET, and Rust. Endpoint selection changes the network destination; it does not expand the service profile or grant target-cloud permissions.

The endpoint override is a local test tool. In a BYOC install, Tensor9 configures the application-to-adapter route as part of the compiled deployment. Do not bake a workstation endpoint into your application image or origin stack.

## Define the contract before running it

Write down the behavior your application depends on. “The request succeeded” is too weak because the target can differ in consistency, conditional writes, retries, metadata, pagination, quotas, and asynchronous completion.

For each operation, record:

| Contract field       | Example for S3 `PutObject`                                                                                   |
| -------------------- | ------------------------------------------------------------------------------------------------------------ |
| Origin request       | Bucket, key, body bytes, content type, and any precondition                                                  |
| Origin response      | Status, entity tag, version information, and request identifiers used by the application                     |
| Native target effect | Object exists in the expected Cloud Storage bucket with identical bytes and expected metadata                |
| Error behavior       | A missing bucket, denied identity, or failed precondition returns an error the application handles correctly |
| Retry behavior       | A transport retry or duplicate request does not create an unexpected second logical resource                 |
| Cleanup              | The test object is deleted and its absence is verified with the native target client                         |

Add one row for every operation your application calls. Do not infer support for an operation that is absent from the directed service page.

## Exercise more than the happy path

Run a small, deterministic suite against the foreground adapter:

<Steps>
  <Step title="Verify native target access">
    Use the target cloud's native client with the same target identity to confirm the test resource is reachable. This separates an adapter problem from a target credential, quota, or network problem.
  </Step>

  <Step title="Run one successful lifecycle">
    Create or write a uniquely named test resource through the origin SDK. Read it back through the origin SDK, then inspect the native target resource and compare the fields your application depends on.
  </Step>

  <Step title="Run one expected failure">
    Use a safe failure such as a missing object or a failed conditional request. Assert the origin-shaped error class, status, retry classification, and request identifiers your application consumes.
  </Step>

  <Step title="Exercise retry and idempotency behavior">
    Repeat only an operation that your application already treats as retryable. Verify the resulting native target state instead of assuming that an origin SDK retry policy has identical effects on every target.
  </Step>

  <Step title="Request an explanation">
    Use [`tensor9 explain`](/cloud-adapter/debugging/explain) to inspect the static mapping. For a covered runtime request, use the signed `x-t9-explain` control and retain its report ID with the application and target request identifiers. An explanation receipt identifies diagnostic evidence; it does not prove success or completion.
  </Step>

  <Step title="Clean up and verify absence">
    Delete resources with the owner that created them. Confirm native target state is clean before stopping the test environment. Preserve sanitized evidence separately from credentials and payloads.
  </Step>
</Steps>

## Repeat the test in a BYOC test install

The installed test proves the boundaries the local process intentionally omits.

<Steps>
  <Step title="Use a representative target">
    Choose the same target cloud, region, form factor, service mapping, and tuning settings you intend to offer customers. Use an isolated vendor-controlled test environment rather than a customer production install.
  </Step>

  <Step title="Compile and review the application">
    Compile the origin stack for the target and review every blocking issue, service mapping, adaptation tier, and documented limitation. Confirm the directed profile still covers the exact operations in your test contract.
  </Step>

  <Step title="Deploy a test release">
    Follow the relevant [BYOC quickstart](/byoc/getting-started/quick-start-terraform) and [deployment workflow](/byoc/fundamentals/deployments). Keep test resource names unique and make cleanup ownership explicit before deployment.
  </Step>

  <Step title="Run from the application boundary">
    Execute the same contract test from the deployed workload, using its real workload identity and network path. Do not substitute an operator credential if the application normally uses a different identity.
  </Step>

  <Step title="Compare all three observations">
    Record the origin-shaped application response, adapter explanation when requested, and native target state. Treat disagreement between them as a failed test even when one surface reports success.
  </Step>

  <Step title="Test restart and update behavior">
    Restart the application and adapter through the normal deployment workflow, then repeat a read and one safe write. For stateful mappings, verify that data and operation status survive the lifecycle events promised by the service page.
  </Step>

  <Step title="Remove the test install">
    Delete application-created fixtures first, then remove the test install using its normal deployment tooling. Verify the target resources named in the cleanup plan are gone or deliberately retained.
  </Step>
</Steps>

## Keep an evidence packet

A useful test result can be reviewed without access to the original environment. Record:

* Application release and service-adapter version.
* Origin and target service names, target cloud, region, and form factor.
* Operation names and sanitized request shapes.
* Expected origin response, native target effect, and error behavior.
* Actual origin status and request ID.
* Explanation report ID, revision, mode, and capture state when Explain was requested.
* Native target request ID and independently observed target state.
* Retry count, elapsed time, and whether an asynchronous operation reached a terminal state.
* Cleanup owner, cleanup result, and any intentionally retained resource.

Do not store authorization headers, access keys, session tokens, signed URLs, customer payloads, or unrestricted debug logs in the packet.

## Add the contract to CI

Keep the local suite small enough to run for each service-adapter or application release. Give each run unique resource names, a bounded timeout, and a cleanup phase that runs after both success and failure. Serialize tests that share a target resource or coordination store.

Run broader load, quota, failover, and upgrade tests on a schedule in a representative BYOC test install. Those tests consume real target capacity and should use explicit budgets and teardown checks.

A profile inspection is a useful early gate, but it is not a runtime test. A local adapter pass is a useful runtime gate, but it is not deployment evidence. Keep all three results separate in CI so a later reader can tell what actually ran.

## When a test fails

First identify the failing boundary:

1. If native target access fails, correct target identity, network, resource, or quota configuration.
2. If the directed profile does not cover the operation, change the application contract or selected mapping.
3. If the local adapter fails but the native target succeeds, collect an explanation and the origin/target request identifiers.
4. If local testing passes but the BYOC test install fails, compare compiled configuration, workload identity, endpoint routing, and deployed adapter version.
5. If the response, explanation, and native target state disagree, stop retrying mutations until you know which effects occurred.

Use the [BYOC service-adapter debugging runbook](/byoc/service-adapters/debugging/overview) to investigate a deployed request safely. The [Explain response reference](/cloud-adapter/debugging/response-headers) defines receipt, report retrieval, ownership, and acknowledgment behavior.

## What these tests do not establish

One passing operation does not establish complete API compatibility. One target does not establish another target. Emulator behavior does not establish a managed cloud service's quotas, latency, failure modes, or consistency. A test install under a vendor-controlled policy does not establish that a customer's policy will grant the same access.

Use the [Service Catalog](/byoc/service-adapters/catalog) and the exact directed service page as the published compatibility contract. Use testing to verify the subset your application actually depends on.
