Commit 1d35a3d
committed
ROX-31495: wiremock for central (#32)
Signed-off-by: Tomasz Janiszewski <tomek@redhat.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
Co-authored-by: Mladen Todorovic <mtodor@gmail.com>
Add Go integration tests for MCP server with WireMock
Implements integration tests that verify MCP server functionality using
stdio transport and WireMock as a mock StackRox Central backend.
**Key Changes:**
- Created integration test suite in `integration/` with build tag
- Implemented stdio-based MCP client in `internal/testutil/mcp.go`
- Added WireMock readiness check in `internal/testutil/wiremock.go`
- Added test fixtures for expected WireMock response data
- Updated Makefile with integration test targets
- Updated GitHub Actions workflow to run integration tests in CI
**Test Coverage:**
- MCP protocol (initialize, list tools)
- Tool invocations (list_clusters, get_deployments_for_cve, etc.)
- Error handling (missing parameters)
- Success and error scenarios
Tests use stdio transport for simplicity and better control over the
MCP server lifecycle. Each test starts a fresh MCP server subprocess
and communicates via JSON-RPC over stdin/stdout.
TODO: Fix WireMock request matching for CVE-2021-44228 deployment query
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
fix: Fix WireMock JSONPath patterns for deployment CVE queries
Apply the same JSONPath fix from commit 01f58ab to deployments.json.
The original mappings used $.query[?(@.query =~ ...)] which looked for
a nested array structure, but gRPC protobuf-to-JSON conversion creates
a simple object with a 'query' field (lowercase).
Changed all deployment CVE mappings from:
$.query[?(@.query =~ /.*CVE-XXX.*/)]
to:
$[?(@.query =~ /.*CVE-XXX.*/)]
This fixes the TestIntegration_GetDeploymentsForCVE_Log4Shell test which
was failing because WireMock couldn't match the gRPC requests.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
test: Unskip Log4Shell integration test
The WireMock JSONPath fix for deployments.json resolves the issue
that was causing this test to fail.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
refactor: Simplify integration tests and remove manual protoc installation
This commit implements two major simplifications to the test infrastructure:
1. **Eliminate TestMain Pre-compilation Pattern**:
- Extract main() body into new internal/app package with Run() function
- Tests now call app.Run() in-process via io.Pipe() instead of subprocess
- Removes 60+ lines of build/setup code from integration_test.go
- Enables full code coverage (previously main.go had 0% coverage)
- Faster test execution (no binary compilation overhead)
- Better debugging (direct function calls vs exec)
2. **Remove Manual Protoc Installation from GitHub Actions**:
- Delete manual protoc 3.20.1 download from workflow
- Rely on Makefile's automatic protoc 32.1 installation
- Single source of truth for protoc version
- Eliminates version mismatch between CI and local dev
Changes:
- Create internal/app/app.go with Run() function extracted from main()
- Update server.Start() to accept optional stdin/stdout parameters
- Refactor testutil.NewMCPClient() to use ServerRunFunc callback
- Remove TestMain, buildMCPBinary, global vars from integration tests
- Update all integration test functions to use createMCPClient() helper
- Remove "Install protoc" step from .github/workflows/test.yml
Benefits:
- 43 net lines removed (-161 +118)
- Better code coverage
- Simpler test maintenance
- Aligned with Go testing best practices
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
fix: Add missing retry/timeout config to integration test setup
The test config was missing RequestTimeout, MaxRetries, InitialBackoff,
and MaxBackoff fields, causing the gRPC client to use zero values instead
of the defaults (30s timeout, 3 retries).
With MaxRetries=0, the retry loop never executed: `for attempt := range 0`
This caused "Request failed after all retries ... attempts=0" warnings
and empty responses from WireMock.
Solution: Explicitly set the retry/timeout fields to match the defaults
defined in internal/config/config.go.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Signed-off-by: Tomasz Janiszewski <tomek@redhat.com>
Add Go integration tests for MCP server with WireMock
Implements integration tests that verify MCP server functionality using
stdio transport and WireMock as a mock StackRox Central backend.
**Key Changes:**
- Created integration test suite in `integration/` with build tag
- Implemented stdio-based MCP client in `internal/testutil/mcp.go`
- Added WireMock readiness check in `internal/testutil/wiremock.go`
- Added test fixtures for expected WireMock response data
- Updated Makefile with integration test targets
- Updated GitHub Actions workflow to run integration tests in CI
**Test Coverage:**
- MCP protocol (initialize, list tools)
- Tool invocations (list_clusters, get_deployments_for_cve, etc.)
- Error handling (missing parameters)
- Success and error scenarios
Tests use stdio transport for simplicity and better control over the
MCP server lifecycle. Each test starts a fresh MCP server subprocess
and communicates via JSON-RPC over stdin/stdout.
TODO: Fix WireMock request matching for CVE-2021-44228 deployment query
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
fix: Fix WireMock JSONPath patterns for deployment CVE queries
Apply the same JSONPath fix from commit 01f58ab to deployments.json.
The original mappings used $.query[?(@.query =~ ...)] which looked for
a nested array structure, but gRPC protobuf-to-JSON conversion creates
a simple object with a 'query' field (lowercase).
Changed all deployment CVE mappings from:
$.query[?(@.query =~ /.*CVE-XXX.*/)]
to:
$[?(@.query =~ /.*CVE-XXX.*/)]
This fixes the TestIntegration_GetDeploymentsForCVE_Log4Shell test which
was failing because WireMock couldn't match the gRPC requests.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
test: Unskip Log4Shell integration test
The WireMock JSONPath fix for deployments.json resolves the issue
that was causing this test to fail.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
refactor: Simplify integration tests and remove manual protoc installation
This commit implements two major simplifications to the test infrastructure:
1. **Eliminate TestMain Pre-compilation Pattern**:
- Extract main() body into new internal/app package with Run() function
- Tests now call app.Run() in-process via io.Pipe() instead of subprocess
- Removes 60+ lines of build/setup code from integration_test.go
- Enables full code coverage (previously main.go had 0% coverage)
- Faster test execution (no binary compilation overhead)
- Better debugging (direct function calls vs exec)
2. **Remove Manual Protoc Installation from GitHub Actions**:
- Delete manual protoc 3.20.1 download from workflow
- Rely on Makefile's automatic protoc 32.1 installation
- Single source of truth for protoc version
- Eliminates version mismatch between CI and local dev
Changes:
- Create internal/app/app.go with Run() function extracted from main()
- Update server.Start() to accept optional stdin/stdout parameters
- Refactor testutil.NewMCPClient() to use ServerRunFunc callback
- Remove TestMain, buildMCPBinary, global vars from integration tests
- Update all integration test functions to use createMCPClient() helper
- Remove "Install protoc" step from .github/workflows/test.yml
Benefits:
- 43 net lines removed (-161 +118)
- Better code coverage
- Simpler test maintenance
- Aligned with Go testing best practices
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
fix: Add missing retry/timeout config to integration test setup
The test config was missing RequestTimeout, MaxRetries, InitialBackoff,
and MaxBackoff fields, causing the gRPC client to use zero values instead
of the defaults (30s timeout, 3 retries).
With MaxRetries=0, the retry loop never executed: `for attempt := range 0`
This caused "Request failed after all retries ... attempts=0" warnings
and empty responses from WireMock.
Solution: Explicitly set the retry/timeout fields to match the defaults
defined in internal/config/config.go.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Signed-off-by: Tomasz Janiszewski <tomek@redhat.com>
cleanup
Signed-off-by: Tomasz Janiszewski <tomek@redhat.com>
Refactor integration tests and migrate to official MCP SDK
This commit refactors the integration test suite and replaces the custom
MCP client implementation with the official MCP Go SDK.
Changes:
1. Table-Driven Tests Refactoring:
- Consolidated 5 individual test functions into 2 table-driven tests
- TestIntegration_ToolCalls: 4 successful tool call scenarios
- TestIntegration_ToolCallErrors: error handling scenarios
- Reduced code duplication by ~50 lines
- Added helper functions: setupInitializedClient, callToolAndGetResult
2. Removed TestMain:
- Eliminated WireMock readiness check from TestMain
- Removed unused imports (fmt, os)
- Simplified test setup (13 lines removed)
3. Migrated to Official MCP Go SDK:
- Replaced custom internal/testutil/mcp.go (202 lines)
- Created internal/testutil/mcp_client.go (141 lines) using SDK
- Uses official mcp.Client and mcp.ClientSession
- Proper type-safe content handling with *mcp.TextContent
- Better error handling (protocol vs tool errors)
Benefits:
- Total code reduction: 99 lines removed
- Better maintainability with table-driven tests
- Future-proof with official SDK
- Consistent with server-side SDK usage
- All tests pass (3 test functions, 5 subtests total)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
fmt
Signed-off-by: Tomasz Janiszewski <tomek@redhat.com>1 parent 9bf4946 commit 1d35a3d
11 files changed
Lines changed: 498 additions & 54 deletions
File tree
- .github/workflows
- cmd/stackrox-mcp
- integration
- internal
- app
- server
- testutil
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
45 | 45 | | |
46 | 46 | | |
47 | 47 | | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
48 | 81 | | |
49 | 82 | | |
50 | 83 | | |
| |||
56 | 89 | | |
57 | 90 | | |
58 | 91 | | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
4 | 4 | | |
5 | 5 | | |
6 | 6 | | |
7 | | - | |
8 | | - | |
9 | | - | |
10 | | - | |
11 | 7 | | |
12 | | - | |
| 8 | + | |
13 | 9 | | |
14 | 10 | | |
15 | | - | |
16 | | - | |
17 | | - | |
18 | | - | |
19 | 11 | | |
20 | 12 | | |
21 | | - | |
22 | | - | |
23 | | - | |
24 | | - | |
25 | | - | |
26 | | - | |
27 | | - | |
28 | | - | |
29 | 13 | | |
30 | 14 | | |
31 | 15 | | |
| |||
38 | 22 | | |
39 | 23 | | |
40 | 24 | | |
41 | | - | |
42 | | - | |
43 | | - | |
44 | | - | |
45 | | - | |
46 | | - | |
47 | | - | |
48 | | - | |
49 | | - | |
50 | | - | |
51 | | - | |
52 | | - | |
53 | | - | |
54 | | - | |
55 | | - | |
56 | | - | |
57 | | - | |
58 | | - | |
59 | | - | |
60 | | - | |
61 | | - | |
62 | | - | |
63 | | - | |
64 | | - | |
65 | | - | |
66 | | - | |
67 | | - | |
68 | | - | |
69 | | - | |
70 | | - | |
| 25 | + | |
71 | 26 | | |
72 | | - | |
| 27 | + | |
73 | 28 | | |
74 | 29 | | |
75 | 30 | | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
14 | 14 | | |
15 | 15 | | |
16 | 16 | | |
| 17 | + | |
| 18 | + | |
17 | 19 | | |
18 | 20 | | |
19 | 21 | | |
20 | 22 | | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
21 | 31 | | |
22 | 32 | | |
23 | 33 | | |
| |||
46 | 56 | | |
47 | 57 | | |
48 | 58 | | |
49 | | - | |
| 59 | + | |
50 | 60 | | |
51 | 61 | | |
52 | 62 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
11 | 11 | | |
12 | 12 | | |
13 | 13 | | |
| 14 | + | |
14 | 15 | | |
15 | 16 | | |
16 | 17 | | |
| |||
40 | 41 | | |
41 | 42 | | |
42 | 43 | | |
43 | | - | |
44 | 44 | | |
45 | 45 | | |
46 | 46 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
0 commit comments