Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions pkg/api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ func decodeJSONResponse(url string, httpResp *http.Response, response interface{
}

bodyStr := strings.TrimSpace(string(body))

if err := json.Unmarshal(body, response); err != nil {
retryable = isRetryableHTTPResponse(httpResp.StatusCode, bodyStr)
log.Errorf(
Expand Down
89 changes: 89 additions & 0 deletions test/integration/api/allocation/invalid_query_parameter_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
package allocation

// Validates that allocation api handles invalid parameters correctly.
// Passing Criteria:
// Returns a HTTP 400 error instead of a response with no error or an HTTP 500 error.

import (
"strings"
"testing"

"github.com/opencost/opencost-integration-tests/pkg/api"
)

func TestAllocationInvalidParameters(t *testing.T) {
apiObj := api.NewAPI()

invalidParameterTestCases := []struct {
name string
window string
filter string
aggregate string
accumulate string
includeidle string
}{
{
name: "ReverseWindow",
window: "2026-06-16T00:00:00Z,2026-06-15T00:00:00Z",
aggregate: "namespace",
},
{
name: "InvalidWindowFormat",
window: "invalid-window-format",
aggregate: "namespace",
},
{
name: "InvalidAggregate",
window: "24h",
aggregate: "invalid-aggregate",
accumulate: "true",
includeidle: "true",
},
{
name: "InvalidFilter",
window: "24h",
filter: "invalid-filter",
accumulate: "true",
includeidle: "true",
aggregate: "namespace",
},
{
name: "InvalidAccumulate",
window: "24h",
accumulate: "invalid-accumulate",
includeidle: "true",
aggregate: "namespace",
},
{
name: "InvalidIncludeIdle",
window: "24h",
accumulate: "true",
includeidle: "invalid-include-idle",
aggregate: "namespace",
},
}

for _, tc := range invalidParameterTestCases {
t.Run(tc.name, func(t *testing.T) {
t.Logf("Testing: %s", tc.name)

_, err := apiObj.GetAllocation(api.AllocationRequest{
Window: tc.window,
Filter: tc.filter,
Accumulate: tc.accumulate,
IncludeIdle: tc.includeidle,
Aggregate: tc.aggregate,
})

// Assert that an error was returned since input is invalid.
if err == nil {
t.Fatalf("Expected an error for invalid input, but got a successful response")
}

// Assert that it is a 400 error.
if !strings.Contains(err.Error(), "HTTP 400") {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think the tests work. You are checking for 400 errors but the API returns 502

t.Fatalf("expected HTTP 400 error, got %v", err)
}
})
}
}
5 changes: 5 additions & 0 deletions test/integration/api/allocation/test.bats
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ setup() {
teardown() {
: # nothing to tear down
}

@test "allocation: controller kind consistency" {
go test allocation_controller_consistency_test.go
}
Expand Down Expand Up @@ -45,3 +46,7 @@ teardown() {
@test "validate_api: validate if all of idle costs are spread" {
go test share_idle_shares_test.go
}

@test "validate_api: validate api can handle invalid parameters" {
go test invalid_query_parameter_test.go
}
57 changes: 57 additions & 0 deletions test/integration/api/asset/invalid_query_parameter_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package assets

// Validates that assets api handles invalid parameters correctly.
// Passing Criteria:
// Returns a HTTP 400 error instead of a response with no error or an HTTP 500 error.

import (
"strings"
"testing"

"github.com/opencost/opencost-integration-tests/pkg/api"
)

func TestAssetInvalidParameters(t *testing.T) {
apiObj := api.NewAPI()

invalidParameterTestCases := []struct {
name string
window string
assetType string
}{
{
name: "ReverseWindow",
window: "2026-06-16T00:00:00Z,2026-06-15T00:00:00Z",
assetType: "node",
},
{
name: "InvalidWindowFormat",
window: "invalid-window-format",
assetType: "node",
},
{
name: "InvalidFilter",
window: "24h",
assetType: "invalid-filter",
},
}

for _, tc := range invalidParameterTestCases {
t.Run(tc.name, func(t *testing.T) {
t.Logf("Testing: %s", tc.name)

_, err := apiObj.GetAssets(api.AssetsRequest{
Window: tc.window,
Filter: tc.assetType,
})

if err == nil {
t.Fatalf("Expected an error for invalid input, but got a successful response")
}

if !strings.Contains(err.Error(), "HTTP 400") {
t.Fatalf("expected HTTP 400 error, got %v", err)
}
})
}
}
4 changes: 4 additions & 0 deletions test/integration/api/asset/test.bats
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ teardown() {
: # nothing to tear down
}

@test "asset: Invalid Parameters" {
go test invalid_query_parameter_test.go
}

@test "asset: Node Labels" {
go test node_labels_test.go
}
Expand Down
Loading