Jelajahi Sumber

Adds a README file for the integration tests

Claudiu Belu 2 minggu lalu
induk
melakukan
5b8e7226e8
1 mengubah file dengan 128 tambahan dan 0 penghapusan
  1. 128 0
      coriolis/tests/integration/README.md

+ 128 - 0
coriolis/tests/integration/README.md

@@ -0,0 +1,128 @@
+# Coriolis Integration Tests
+
+Integration tests that exercise the full Coriolis service stack
+(conductor, scheduler, worker, and REST API) in a single process,
+using an in-memory transport and a temporary SQLite database.
+No RabbitMQ, Keystone, Barbican, or external cloud is required.
+
+## How it works
+
+The test harness (`harness.py`) performs a one-time setup per process:
+
+1. Creates a temporary working directory and SQLite database.
+2. Overrides `oslo.config` so all services use `fake://` messaging and
+   the temporary DB.
+3. Runs `db_sync` to apply all schema migrations.
+4. Starts conductor, scheduler, and worker inside the test process. The
+   worker runs task code inline (not in subprocesses) so that in-process
+   RPC calls reach the conductor.
+5. Serves the REST API on a random local port, with Keystone auth replaced by
+   a no-op middleware that injects a fixed admin context.
+6. Injects a fake block-device provider (`providers/test_provider/`)
+   that uses `scsi_debug` virtual disks as source and destination storage.
+
+Teardown (registered with `atexit`) stops all services, removes the
+working directory, and unloads the `scsi_debug` kernel module.
+
+## Prerequisites
+
+### System packages
+
+| Package | Why |
+|---------|-----|
+| `scsi_debug` kernel module | Virtual block devices used as source / destination storage |
+| `lsblk`, `udevadm` | Device discovery after hot-adding a `scsi_debug` host |
+| `dd`, `sync`, `cmp` | Test-pattern writes and device comparison |
+| `modprobe` | Loading and unloading `scsi_debug` |
+
+On Ubuntu / Debian:
+```bash
+sudo apt-get install util-linux kmod
+# scsi_debug ships with the standard kernel; no extra package is needed
+```
+
+### Python dependencies
+
+All runtime and test dependencies are declared in `requirements.txt` and
+`test-requirements.txt`. Use tox; do not install packages globally.
+
+Key packages used by the harness:
+
+- `coriolisclient`: REST API client
+- `keystoneauth1`: session used by `coriolisclient` (auth is bypassed in tests)
+- `oslo.messaging`, `oslo.config`, `oslo.log`, `oslo.service`
+
+### SSH key (for provider connection info)
+
+The test provider connection info includes a `pkey_path` field that
+defaults to `/root/.ssh/id_rsa`. Override it with the environment
+variable `CORIOLIS_TEST_SSH_KEY_PATH` if the key lives elsewhere.
+
+> The key is passed through to the provider's connection info dictionary
+> but the smoke tests and current provider implementation do not actually
+> open an SSH connection, so any readable file path satisfies the field.
+
+### Root access
+
+The tests must run as root because:
+- `modprobe` requires root to load/unload `scsi_debug`.
+- Writing to the `scsi_debug` sysfs add-host knob (`/sys/bus/pseudo/…`)
+  requires root.
+- Raw block-device reads/writes (`dd`, `cmp`) require root.
+
+Tests that extend `CoriolisIntegrationTestBase` call `os.geteuid()` in
+`setUpClass` and skip automatically when not running as root.
+
+## Running the tests
+
+```bash
+# All integration tests
+sudo tox -e integration
+
+# A single test module
+sudo tox -e integration -- --no-discover coriolis/tests/integration/test_smoke.py
+
+# A specific test class or method
+sudo tox -e integration -- --no-discover coriolis.tests.integration.test_transfer.ReplicaTransferIntegrationTest.test_incremental_replica_transfer
+```
+
+> `sudo` is required because `tox` itself must run as root so that the
+> test process inherits root privileges.
+
+## Test modules
+
+| Module | Base class | Description |
+|--------|-----------|-------------|
+| `test_smoke.py` | `CoriolisIntegrationTestBase` | Verifies API reachability and basic endpoint / transfer CRUD. No block devices needed. |
+| `test_transfer.py` | `ReplicaIntegrationTestBase` | Full replica transfer: initial full sync then incremental after a source mutation; asserts byte-level device equality. |
+| `test_deployment.py` | `ReplicaIntegrationTestBase` | Runs a replica execution, then creates a deployment from it and asserts it reaches `COMPLETED`. |
+| `test_failure_recovery.py` | `ReplicaIntegrationTestBase` | Injects an exception into the provider's `deploy_replica_target_resources`; asserts that the execution reaches `ERROR`. |
+
+## Directory structure
+
+```
+integration/
+├── base.py             # base test classes
+├── harness.py          # _IntegrationHarness singleton
+├── utils.py            # scsi_debug helpers, device I/O utilities
+├── test_smoke.py
+├── test_transfer.py
+├── test_deployment.py
+├── test_failure_recovery.py
+└── providers/
+    └── test_provider/  # Fake cloud provider backed by scsi_debug devices
+        ├── __init__.py
+        ├── exp.py      # Export provider
+        └── imp.py      # Import provider
+```
+
+## Adding new tests
+
+1. Extend `CoriolisIntegrationTestBase` for API-level tests that do not
+   need block devices, or `ReplicaIntegrationTestBase` for tests that
+   exercise the transfer / deployment pipeline with real disk I/O.
+2. Use `self.assertExecutionCompleted()`, `self.assertExecutionErrored()`,
+   and `self.assertDeploymentCompleted()` to wait for and assert on
+   async operation outcomes.
+3. Do not start the harness manually; `setUpClass` in the base class
+   calls `_IntegrationHarness.get()`, which is idempotent.