Skip to content

Commit

Permalink
..
Browse files Browse the repository at this point in the history
  • Loading branch information
zelosleone committed Dec 25, 2024
1 parent b241b8d commit 07faec8
Show file tree
Hide file tree
Showing 2 changed files with 159 additions and 47 deletions.
116 changes: 96 additions & 20 deletions .github/workflows/openapi-integration-tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,22 +17,79 @@ env:
CARGO_TERM_COLOR: always
RUST_LOG: debug
WORKER_SERVICE_HTTP_PORT: 9005
CARGO_INCREMENTAL: 0 # Disable incremental compilation for faster builds
CARGO_NET_RETRY: 10 # Increase network retry attempts
RUSTC_WRAPPER: sccache # Use sccache for faster compilation
SCCACHE_CACHE_SIZE: 10G
RUST_BACKTRACE: 1

jobs:
openapi-integration-tests:
name: Run OpenAPI Integration Tests
runs-on: ubuntu-latest

rust-unit-tests:
name: Run Rust Unit Tests
runs-on: ubuntu-latest-16-cores
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 1

- name: Install sccache
run: |
SCCACHE_VERSION=v0.5.4
curl -L "https://github.com/mozilla/sccache/releases/download/${SCCACHE_VERSION}/sccache-${SCCACHE_VERSION}-x86_64-unknown-linux-musl.tar.gz" | tar xz
sudo mv sccache-*/sccache /usr/local/bin/sccache
echo "$(which sccache)"
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
with:
components: rustfmt, clippy

- name: Cache Rust dependencies
uses: actions/cache@v3
with:
path: |
~/.cargo/registry
~/.cargo/git
target
~/.cache/sccache
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}-${{ github.sha }}
restore-keys: |
${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}-
${{ runner.os }}-cargo-
- name: Start sccache server
run: sccache --start-server

- name: Run Unit Tests
run: |
cd golem-worker-service-base
cargo test gateway_api_definition::http::openapi_export -- --nocapture --test-threads $(nproc)
cargo test gateway_api_definition::http::swagger_ui -- --nocapture --test-threads $(nproc)
- name: Print sccache stats
run: sccache --show-stats

python-integration-tests:
name: Run Python Integration Tests
needs: rust-unit-tests
runs-on: ubuntu-latest-16-cores
strategy:
fail-fast: false
matrix:
test-group: [openapi, swagger-ui, edge-cases]
include:
- test-group: openapi
test-pattern: "test_openapi_export"
- test-group: swagger-ui
test-pattern: "test_swagger_ui"
- test-group: edge-cases
test-pattern: "test_.*_edge_cases"

steps:
- uses: actions/checkout@v4
with:
fetch-depth: 1

- name: Install Protoc
uses: arduino/setup-protoc@v3
with:
Expand All @@ -42,28 +99,22 @@ jobs:
uses: actions/setup-python@v5
with:
python-version: '3.10'
cache: 'pip'

- name: Install Python dependencies
run: |
python -m pip install --upgrade pip
pip install -r tests/requirements.txt
- name: Run Unit Tests
run: |
cd golem-worker-service-base
cargo test gateway_api_definition::http::openapi_export -- --nocapture
cargo test gateway_api_definition::http::swagger_ui -- --nocapture
pip install pytest pytest-asyncio pytest-xdist
- name: Build and Start Worker Service
run: |
cd golem-worker-service-base
cargo build --bin golem-worker-service
RUSTFLAGS="-C target-cpu=native" cargo build --release --bin golem-worker-service
# Create config directory and data directory
mkdir -p config data
touch data/golem_worker.sqlite
# Create worker service config
cat << EOF > config/worker-service.toml
environment = "local"
Expand All @@ -79,21 +130,46 @@ jobs:
url = "sqlite://../data/golem_worker.sqlite"
EOF
# Start worker service
cargo run --bin golem-worker-service &
./target/release/golem-worker-service &
# Wait for service to be ready
echo "Waiting for worker service to be ready..."
timeout 30 bash -c "until curl -s http://localhost:${WORKER_SERVICE_HTTP_PORT}/health > /dev/null 2>&1; do sleep 1; done"
echo "Worker service is running!"
- name: Run HTTP Tests
- name: Run Integration Tests
run: |
python tests/api_client_test.py
pytest tests/api_client_test.py -v -n auto -k "${{ matrix.test-pattern }}" --asyncio-mode=auto
- name: Upload Test Results
if: always()
uses: actions/upload-artifact@v4
with:
name: test-results
path: test-output/
name: test-results-${{ matrix.test-group }}
path: test-output/

test-summary:
name: Summarize Test Results
needs: [rust-unit-tests, python-integration-tests]
runs-on: ubuntu-latest
if: always()
steps:
- name: Download Test Results
uses: actions/download-artifact@v4
with:
path: test-results

- name: Generate Test Summary
run: |
echo "## Test Results Summary" >> $GITHUB_STEP_SUMMARY
echo "### Rust Unit Tests" >> $GITHUB_STEP_SUMMARY
if [ "${{ needs.rust-unit-tests.result }}" == "success" ]; then
echo "✅ Passed" >> $GITHUB_STEP_SUMMARY
else
echo "❌ Failed" >> $GITHUB_STEP_SUMMARY
fi
echo "### Python Integration Tests" >> $GITHUB_STEP_SUMMARY
if [ "${{ needs.python-integration-tests.result }}" == "success" ]; then
echo "✅ Passed" >> $GITHUB_STEP_SUMMARY
else
echo "❌ Failed" >> $GITHUB_STEP_SUMMARY
fi
90 changes: 63 additions & 27 deletions tests/api_client_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import logging
import wasmtime
from wasi.http import *
import pytest

# Configure logging
logging.basicConfig(
Expand Down Expand Up @@ -111,10 +112,16 @@ async def get_swagger_ui(self, theme: str = None, api_id: str = "default", versi

return response.body.decode()

async def test_openapi_export():
@pytest.fixture
async def client():
"""Fixture to create and manage GolemApiClient instance"""
client = GolemApiClient()
yield client

@pytest.mark.asyncio
async def test_openapi_export(client):
"""Test OpenAPI export functionality matching openapi_export.rs"""
logger.info("Starting OpenAPI export tests...")
client = GolemApiClient()

# Test JSON export (default format)
json_spec = await client.export_openapi("test-api", "1.0.0", "json")
Expand All @@ -132,21 +139,19 @@ async def test_openapi_export():
custom_spec = await client.export_openapi("custom-api", "2.0.0", "json")
assert custom_spec["info"]["title"] == "custom-api API"
assert custom_spec["info"]["version"] == "2.0.0"

logger.info("OpenAPI export tests passed successfully")

async def test_swagger_ui():
@pytest.mark.asyncio
async def test_swagger_ui(client):
"""Test Swagger UI functionality matching swagger_ui.rs"""
logger.info("Starting Swagger UI tests...")
client = GolemApiClient()

# Test default configuration (no theme)
default_ui = await client.get_swagger_ui()
assert "<!DOCTYPE html>" in default_ui
assert "<html lang=\"en\">" in default_ui
assert "swagger-ui-dist" in default_ui
assert "deepLinking: true" in default_ui
assert "API Documentation" in default_ui # Default title
assert "API Documentation" in default_ui

# Test dark theme
dark_ui = await client.get_swagger_ui(theme="dark")
Expand All @@ -157,25 +162,56 @@ async def test_swagger_ui():
# Test custom API configuration
custom_ui = await client.get_swagger_ui(api_id="test-api", version="2.0")
assert "/v1/api/definitions/test-api/version/2.0/export" in custom_ui

logger.info("Swagger UI tests passed successfully")

async def run_tests():
"""Run all tests"""
try:
logger.info("Starting test suite...")

print("Testing OpenAPI export...")
await test_openapi_export()

print("Testing Swagger UI...")
await test_swagger_ui()

logger.info("All tests completed successfully!")
print("All tests completed successfully!")
except Exception as e:
logger.error(f"Test suite failed: {str(e)}")
raise
@pytest.mark.asyncio
async def test_openapi_export_edge_cases(client):
"""Test edge cases for OpenAPI export"""
logger.info("Starting OpenAPI export edge cases tests...")

# Test very long API ID
long_id = "a" * 256
long_spec = await client.export_openapi(long_id, "1.0.0", "json")
assert long_spec["info"]["title"] == f"{long_id} API"

# Test special characters
special_id = "test-api!@#$%"
special_spec = await client.export_openapi(special_id, "1.0.0", "json")
assert special_spec["info"]["title"] == f"{special_id} API"

# Test empty version
empty_version_spec = await client.export_openapi("test-api", "", "json")
assert empty_version_spec["info"]["version"] == ""

# Test concurrent requests
tasks = [
client.export_openapi("test-api", "1.0.0", "json")
for _ in range(5)
]
results = await asyncio.gather(*tasks)
assert all(spec["info"]["title"] == "test-api API" for spec in results)

if __name__ == "__main__":
asyncio.run(run_tests())
@pytest.mark.asyncio
async def test_swagger_ui_edge_cases(client):
"""Test edge cases for Swagger UI"""
logger.info("Starting Swagger UI edge cases tests...")

# Test empty theme
empty_theme = await client.get_swagger_ui(theme="")
assert "<!DOCTYPE html>" in empty_theme
assert "background-color: #1a1a1a" not in empty_theme

# Test XSS prevention
xss_api_id = "<script>alert('xss')</script>"
xss_response = await client.get_swagger_ui(api_id=xss_api_id)
assert "<script>alert('xss')</script>" not in xss_response

# Test invalid theme
invalid_theme = await client.get_swagger_ui(theme="invalid_theme")
assert "background-color: #1a1a1a" not in invalid_theme

# Test CORS headers
response = await client.make_request(
'OPTIONS',
f"{client.base_url}/docs"
)
assert 'Access-Control-Allow-Origin' in response.headers

0 comments on commit 07faec8

Please sign in to comment.