Skip to content

A testbench for Google Cloud Storage client libraries.

License

Notifications You must be signed in to change notification settings

anuragsrivstv/storage-testbench

 
 

Repository files navigation

Storage Testbench

This is not an officially supported Google product

This repository is used by Storage Client libraries to test integration tests locally and reproduce Storage API transient errors. The testbench emulates the Storage API and is expected to be used by Storage library maintainers.

Table of Contents

Issue Policy

Repository provides no dedicated support for issues filed. Issues will be addressed when time permits.

What is this testbench?

This testbench fakes the Google Cloud Storage (GCS) API. You can configure the GCS client libraries to make calls to this fake rather than to the actual API.

  • The testbench fakes the JSON API, both over REST and gRPC. It has limited support for the XML API.
  • Generally, the error codes are similar to the ones generated by GCS, but the error messages are not.
  • The testbench performs far fewer error checks, and no permission checks (ACL/IAM).

When to use this testbench

In general, this testbench is best suited for integration tests that are hard (or just annoying) to reliably run against production. The primary example of this are errors that make the client library go through its retry path.

This testbench can be useful to test HMAC keys, which are really hard to test against production due to quota restrictions.

It is useful as well to test features that are not yet deployed to production: you can implement them in the testbench and then write the library code before production is "ready".

How to use this testbench

Initial set up

  1. Set up python if you haven't already

  2. Clone this repository

    From the terminal:

    git clone https://github.com/googleapis/storage-testbench.git
  3. Switch to the cloned directory:

    cd storage-testbench
  4. Create a virtual environment

    • keep this virtual environment active whenever you run the testbench
  5. Install dependencies:

    pip install -e .

Run the testbench

To start the testbench, run this command from a terminal:

gunicorn --bind "localhost:9000" --worker-class sync --threads 10 --reload --access-logfile - "testbench:run()"

⚠️ Ensure that the virtual environment you created to install the dependencies is active.

Start the gRPC server

If you want to test the gRPC API, you must make a request which will start the testbench's gRPC server. Also, the gRPC server must run on a different port than the HTTP server. To serve gRPC requests on port 8888, run:

curl -s --retry 5 --retry-max-time 40 "http://localhost:9000/start_grpc?port=8888"

Check that the testbench is running

Ensure the testbench is running by sending it a request from a different terminal, such as:

curl -X GET localhost:9000

The response you get should be: OK

Now you can use the testbench (while it's running) with the client libraries.

Updating Proto Files

From time to time you may need to update the files generated by protobuf and gRPC. To do so, clone the protos and run the grpc_tools generator:

cd $HOME/storage-testbench

# This creates a new directory with the protos from `googleapis`.  If
# the clone already exists use:
#    git -C $HOME/googleapis pull
git -C $HOME clone https://github.com/googleapis/googleapis

pip install grpcio-tools
python -m grpc_tools.protoc -I$HOME/googleapis \
    --python_out=. --grpc_python_out=. \
    $HOME/googleapis/google/iam/v1/iam_policy.proto
python -m grpc_tools.protoc -I$HOME/googleapis \
    --python_out=. --grpc_python_out=. \
    $HOME/googleapis/google/iam/v1/options.proto
python -m grpc_tools.protoc -I$HOME/googleapis \
    --python_out=. --grpc_python_out=. \
    $HOME/googleapis/google/iam/v1/policy.proto
python -m grpc_tools.protoc -I$HOME/googleapis \
    --python_out=. --grpc_python_out=. \
    $HOME/googleapis/google/storage/v2/storage.proto

Then commit the files generated in google/**:

git commit -m"chore: update protos" google

Force Failures

You can force the following failures by using the x-goog-emulator-instructions header. The x-goog-testbench-instructions header is deprecated, but supported for backwards compatibility and provides the same functionality as x-goog-emulator-instructions, please change your code to use x-goog-emulator-instructions instead.

return-broken-stream

Set request headers with x-goog-emulator-instructions: return-broken-stream. Testbench will fail after sending 1024*1024 bytes.

return-corrupted-data

Set request headers with x-goog-emulator-instructions: return-corrupted-data. Testbench will return corrupted data.

stall-always

Set request headers with x-goog-emulator-instructions: stall-always. Testbench will stall at the beginning.

stall-at-256KiB

Set request headers with x-goog-emulator-instructions: stall-at-256KiB. Testbench will stall at 256KiB bytes.

return-503-after-256K

Set request headers with x-goog-emulator-instructions: return-503-after-256K. Testbench will return a HTTP 503 after sending 256KiB bytes.

return-503-after-256K/retry-N

Set request headers with x-goog-emulator-instructions: return-503-after-256K/retry-1 up to x-goog-emulator-instructions: return-503-after-256K/retry-N.

For N==1 and N==2 behave like return-305-after-256K, for N>=3 ignore the failure instruction and return successfully. This is used to test failures during retry, the client cooperates by sending the retry counter in the failure instructions.

Retry Test API

The "Retry Test API" offers a mechanism to describe more complex retry scenarios while sending a single, constant header through all the HTTP requests from a test program. Retry Test provides accounting of failures used to validate the expected failures were experienced by the testbench and not accidentally missed.

Previous versions of the GCS testbench used a custom header in the RPC to control the behavior of each RPC, for some test scenarios this required sending different header with the first retry attempt vs. subsequent attempts. Producing different headers in each attempt is not easy to implement with some client libraries.

Sending a constant header with all RPCs can be implemented across all client libraries, and to some degree decouples the test setup from the test execution.

Creating a new Retry Test

The following cURL request will create a Retry Test resource which emits a 503 when a buckets list operation is received by the testbench with the returned retry test ID.

curl -X POST "http://localhost:9000/retry_test" -H 'Content-Type: application/json' \
     -d '{"instructions":{"storage.buckets.list": ["return-503"]}}'

Get a Retry Test resource

Get Retry Test resource by id "1d05c20627844214a9ff7cbcf696317d".

curl -X GET "http://localhost:9000/retry_test/1d05c20627844214a9ff7cbcf696317d"

Delete a Retry Test resource

Delete Retry Test resource by id "1d05c20627844214a9ff7cbcf696317d".

curl -X DELETE "http://localhost:9000/retry_test/1d05c20627844214a9ff7cbcf696317d"

Causing a failure using x-retry-test-id header

The following cURL request will attempt to list buckets and the testbench will emit a 503 error once based on the Retry Test created above. Subsequent list buckets operations will succeed.

curl -H "x-retry-test-id: 1d05c20627844214a9ff7cbcf696317d" "http://localhost:9100/storage/v1/b?project=test"

Forced Failures Supported

Failure Id Description
return-X Testbench will fail with HTTP code provided for X, e.g. return-503 returns a 503
return-X-after-YK Testbench will return X after YKiB of uploaded data
return-broken-stream-final-chunk-after-YB Testbench will break connection on final chunk of a resumable upload after Y bytes
return-broken-stream Testbench will fail after a few bytes
return-broken-stream-after-YK Testbench will fail after YKiB of downloaded data
return-reset-connection Testbench will fail with a reset connection

About

A testbench for Google Cloud Storage client libraries.

Resources

License

Code of conduct

Security policy

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Python 99.9%
  • Dockerfile 0.1%