Load Testing Suite
This directory contains load and integration tests for Gitness using Vegeta HTTP load testing tool and Testify assertions.
Test Suite Overview
Available Tests
-
TestUsageMetricsLoad - Load tests the usage metrics endpoint
- Tests:
/api/v1/spaces/{space}/metricendpoint - Rate: 50 requests/second
- Duration: 30 seconds
- Assertions: 95% success rate, P95 < 500ms
- Tests:
-
TestRepositoryImportAndFileAccess - Integration test for repository operations
- Authenticates to Gitness
- Imports
github.com/google/uuidrepository via/api/v1/repos/import - Waits for import completion by polling the repository status
- Fetches README.md from the imported repository
- Validates file content
- Cleans up (deletes repository via
/api/v1/repos/{space}/{repo})
-
TestFileAccessLoad - Load tests file access endpoint
- Sets up: Imports a test repository from GitHub
- Tests: File content endpoint with high concurrency
- Rate: 100 requests/second
- Duration: 30 seconds
- Assertions: 99% success rate, P95 < 200ms, P99 < 500ms
- Cleans up: Deletes the test repository
Prerequisites
- Running Gitness instance (local or remote)
- Admin credentials for authentication
- Network access to GitHub for repository import
Environment Variables
Set these environment variables before running the tests:
| Variable | Required | Default | Description |
|---|---|---|---|
GITNESS_E2E_TEST_ENABLED |
Yes | - | Must be "true" to run tests |
GITNESS_BASE_URL |
No | http://localhost:3000 |
Gitness instance URL |
GITNESS_AUTH_TOKEN |
No | - | Pre-authenticated token (if not set, will login) |
GITNESS_PRINCIPAL_ADMIN_EMAIL |
No* | - | Admin email for login |
GITNESS_PRINCIPAL_ADMIN_PASSWORD |
No* | - | Admin password for login |
SPACE_REF |
No | default |
Space identifier to use |
* Required if GITNESS_AUTH_TOKEN is not provided
Running the Tests
Run All Tests
# Set required environment variables
export GITNESS_E2E_TEST_ENABLED=true
export GITNESS_BASE_URL=http://localhost:3000
export GITNESS_PRINCIPAL_ADMIN_EMAIL=admin@example.com
export GITNESS_PRINCIPAL_ADMIN_PASSWORD=adminpassword
# Run all tests
cd tests/load
go test -v
Run Specific Test
# Run only the repository import test
go test -v -run TestRepositoryImportAndFileAccess
# Run only the file access load test
go test -v -run TestFileAccessLoad
# Run only the usage metrics load test
go test -v -run TestUsageMetricsLoad
Using Pre-authenticated Token
If you already have an authentication token:
export GITNESS_E2E_TEST_ENABLED=true
export GITNESS_AUTH_TOKEN="your-token-here"
go test -v
Run with Verbose Output
go test -v -count=1
The -count=1 flag disables test caching, ensuring fresh results.
Test Output
Each test provides detailed output including:
Load Test Metrics
=== RUN TestFileAccessLoad
=== File Access Load Test Results ===
Requests: 3000
Success Rate: 99.97%
Mean Latency: 45.2ms
P50 Latency: 38ms
P95 Latency: 125ms
P99 Latency: 287ms
Max Latency: 450ms
Throughput: 99.85 req/s
--- PASS: TestFileAccessLoad (35.42s)
Integration Test Output
=== RUN TestRepositoryImportAndFileAccess
usage_metrics_test.go:168: Successfully authenticated
usage_metrics_test.go:177: Repository imported: uuid-test-1234567890 (ID: 42)
usage_metrics_test.go:180: Waiting for repository import to complete...
usage_metrics_test.go:184: Repository import completed successfully
usage_metrics_test.go:192: Successfully fetched README.md (2456 bytes)
usage_metrics_test.go:199: Repository cleaned up successfully
--- PASS: TestRepositoryImportAndFileAccess (87.23s)
Test Customization
Adjust Load Test Parameters
Edit the test file to modify load test parameters:
// In TestFileAccessLoad
rate := vegeta.Rate{Freq: 100, Per: time.Second} // Change request rate
duration := 30 * time.Second // Change test duration
// Adjust assertions
assert.GreaterOrEqual(t, metrics.Success, 0.99, "Success rate should be at least 99%")
assert.LessOrEqual(t, metrics.Latencies.P95, 200*time.Millisecond, "P95 under 200ms")
Change Test Repository
To test with a different repository, modify the import request in the importRepository function:
importReq := repoctl.ImportInput{
ParentRef: spaceRef,
Identifier: identifier,
Description: "Test repository",
Provider: importer.Provider{
Type: importer.ProviderTypeGitHub, // or ProviderTypeGitLab, ProviderTypeBitbucket, etc.
},
ProviderRepo: "your-org/your-repo", // Change this
}
Available provider types:
importer.ProviderTypeGitHub- GitHub repositoriesimporter.ProviderTypeGitLab- GitLab repositoriesimporter.ProviderTypeBitbucket- Bitbucket repositoriesimporter.ProviderTypeGitea- Gitea repositoriesimporter.ProviderTypeGogs- Gogs repositoriesimporter.ProviderTypeAzure- Azure DevOps repositories
Adjust Timeouts
// Repository import timeout
err = waitForRepositoryReady(ctx, baseURL, authToken, spaceRef, repoIdentifier,
5*time.Minute) // Increase if importing large repositories
Troubleshooting
Tests are Skipped
Symptom: Tests show as SKIP instead of running
Solution: Ensure GITNESS_E2E_TEST_ENABLED=true is set:
export GITNESS_E2E_TEST_ENABLED=true
Authentication Failures
Symptom: Failed to authenticate errors
Solutions:
- Verify credentials are correct
- Check Gitness instance is running and accessible
- Verify the base URL is correct
- Try using a pre-authenticated token instead
Repository Import Timeout
Symptom: repository import timed out error
Solutions:
- Check GitHub is accessible from Gitness instance
- Increase timeout in
waitForRepositoryReady - Verify the repository exists and is public
- Check Gitness logs for import errors
Load Test Failures
Symptom: Success rate below threshold or high latency
Possible Causes:
- Gitness instance is under-resourced
- Network latency issues
- Database performance bottlenecks
- Load test rate is too aggressive
Solutions:
- Reduce request rate:
rate := vegeta.Rate{Freq: 50, Per: time.Second} - Scale up Gitness instance resources
- Run tests from same network/region as Gitness
- Relax assertion thresholds temporarily to understand baseline
Import Request JSON Unmarshal Error
Symptom: import failed with status 400: {"message":"Invalid Request Body: json: cannot unmarshal string into Go struct field ImportInput.provider of type importer.Provider."}
Cause: The Provider field must be a struct, not a string
Solution: Ensure you're using the correct structure:
// ✓ Correct - Provider is a struct
Provider: importer.Provider{
Type: importer.ProviderTypeGitHub,
}
// ✗ Wrong - Provider as string (deprecated)
Provider: "github"
Performance Baselines
Expected performance for a properly configured Gitness instance:
| Metric | File Access | Usage Metrics |
|---|---|---|
| Success Rate | ≥99% | ≥95% |
| Mean Latency | <50ms | <100ms |
| P95 Latency | <200ms | <500ms |
| P99 Latency | <500ms | <1s |
| Throughput | ~100 req/s | ~50 req/s |
These baselines assume:
- Local or low-latency network
- Adequate system resources (2+ CPU cores, 4GB+ RAM)
- No other significant load on the system
Integration with CI/CD
GitHub Actions Example
name: Load Tests
on:
schedule:
- cron: '0 2 * * *' # Daily at 2 AM
workflow_dispatch:
jobs:
load-test:
runs-on: ubuntu-latest
services:
gitness:
image: harness/gitness:latest
ports:
- 3000:3000
env:
GITNESS_PRINCIPAL_ADMIN_EMAIL: admin@test.com
GITNESS_PRINCIPAL_ADMIN_PASSWORD: testpassword
steps:
- uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: '1.24'
- name: Wait for Gitness
run: |
timeout 60 bash -c 'until curl -f http://localhost:3000/api/v1/health; do sleep 2; done'
- name: Run Load Tests
env:
GITNESS_E2E_TEST_ENABLED: true
GITNESS_BASE_URL: http://localhost:3000
GITNESS_PRINCIPAL_ADMIN_EMAIL: admin@test.com
GITNESS_PRINCIPAL_ADMIN_PASSWORD: testpassword
run: |
cd tests/load
go test -v -timeout 15m
Implementation Details
Type System
The tests use actual Gitness types from the project instead of custom mock types:
-
repoctl.ImportInput- Repository import request structure- Uses
importer.Providerstruct with typed provider constants - Includes
ParentReffield to specify the target space
- Uses
-
repoctl.RepositoryOutput- Repository response structure- Contains all repository metadata and state information
- Includes
Importingboolean field to track import status
-
importer.Provider- Provider configuration- Type-safe provider constants (GitHub, GitLab, Bitbucket, etc.)
- Supports authentication credentials if needed
API Endpoints Used
The tests interact with these Gitness API endpoints:
| Endpoint | Method | Purpose |
|---|---|---|
/api/v1/login |
POST | Authenticate and obtain access token |
/api/v1/repos/import |
POST | Import repository from external provider |
/api/v1/repos/{space}/{repo} |
GET | Get repository details and status |
/api/v1/repos/{space}/{repo} |
DELETE | Delete repository |
/api/v1/repos/{space}/{repo}/+/content/{path}?git_ref={ref} |
GET | Fetch file content from repository |
/api/v1/spaces/{space}/metric |
GET | Retrieve usage metrics for a space |
Authentication
Tests support two authentication methods:
- Token-based: Use
GITNESS_AUTH_TOKENenvironment variable - Credential-based: Use
GITNESS_PRINCIPAL_ADMIN_EMAILandGITNESS_PRINCIPAL_ADMIN_PASSWORD
The authenticate function handles credential-based login and token extraction.
Contributing
When adding new load tests:
- Follow the existing test patterns
- Use testify assertions for clarity
- Use project types - Import types from
app/api/controllerandapp/servicespackages instead of creating custom structs - Always clean up resources (repositories, etc.)
- Add appropriate environment variable documentation
- Include expected performance baselines
- Use meaningful test and metric names
- Add test description in this README
Dependencies
- vegeta - HTTP load testing tool
- testify - Testing toolkit with assertions
Both are already included in go.mod.