Skip to content

Commit

Permalink
feat: added validation method for pagination cache
Browse files Browse the repository at this point in the history
  • Loading branch information
Aerex committed Nov 16, 2023
1 parent a3f3f5d commit 9ac63c3
Show file tree
Hide file tree
Showing 3 changed files with 121 additions and 0 deletions.
44 changes: 44 additions & 0 deletions bluemix/configuration/config_helpers/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
package config_helpers

import (
"encoding/base64"
gourl "net/url"
"os"
"path/filepath"
"runtime"
Expand Down Expand Up @@ -91,3 +93,45 @@ func UserHomeDir() string {

return os.Getenv("HOME")
}

// IsValidPaginationNextURL will return true if the provided nextURL has the expected queries provided
func IsValidPaginationNextURL(nextURL string, cursorQueryParamName string, expectedQueries gourl.Values) bool {
parsedURL, parseErr := gourl.Parse(nextURL)
// NOTE: ignore handling error(s) since if there error(s)
// we can assume the url is invalid
if parseErr != nil {
return false
}

// retrive encoded cursor
// eg. /api?cursor=<encode_string>
queries := parsedURL.Query()
encodedQuery := queries.Get(cursorQueryParamName)
if encodedQuery == "" {
return false

}
// decode string and parse encoded queries
decodedQuery, decodedErr := base64.RawURLEncoding.DecodeString(encodedQuery)
if decodedErr != nil {
return false
}
queries, parsedErr := gourl.ParseQuery(string(decodedQuery))
if parsedErr != nil {
return false
}

// compare expected queries that should match
// NOTE: assume queries are single value queries.
// if multi-value queries will check the first query
for expectedQuery := range expectedQueries {
paginationQueryValue := queries.Get(expectedQuery)
expectedQueryValue := expectedQueries.Get(expectedQuery)
if paginationQueryValue != expectedQueryValue {
return false
}

}

return true
}
61 changes: 61 additions & 0 deletions bluemix/configuration/config_helpers/helpers_test.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package config_helpers

import (
"encoding/base64"
"io/ioutil"
gourl "net/url"
"os"
"path/filepath"
"strings"
Expand Down Expand Up @@ -103,3 +105,62 @@ func TestConfigDir_IbmCloudConfigHomeSet_Exists(t *testing.T) {
os.Setenv("IBMCLOUD_CONFIG_HOME", userHome)
assert.Equal(userHome, ConfigDir())
}

func TestIsValidPaginationNextURL(t *testing.T) {
assert := assert.New(t)

testCases := []struct {
name string
nextURL string
encodedQueryParam string
expectedQueries gourl.Values
isValid bool
}{
{
name: "return true for matching expected queries in pagination url",
nextURL: "/api/example?cursor=" + base64.RawURLEncoding.EncodeToString([]byte("limit=100&active=true")),
encodedQueryParam: "cursor",
expectedQueries: gourl.Values{
"limit": []string{"100"},
"active": []string{"true"},
},
isValid: true,
},
{
name: "return true for matching expected queries with extraneous queries in pagination url",
nextURL: "/api/example?cursor=" + base64.RawURLEncoding.EncodeToString([]byte("limit=100&active=true&extra=foo")),
encodedQueryParam: "cursor",
expectedQueries: gourl.Values{
"limit": []string{"100"},
"active": []string{"true"},
},
isValid: true,
},
{
name: "return false for different limit in pagination url",
nextURL: "/api/example?cursor=" + base64.RawURLEncoding.EncodeToString([]byte("limit=200")),
encodedQueryParam: "cursor",
expectedQueries: gourl.Values{
"limit": []string{"100"},
},
isValid: false,
},
{
name: "return false for different query among multiple parameters in the pagination url",
nextURL: "/api/example?cursor=" + base64.RawURLEncoding.EncodeToString([]byte("limit=100&active=true")),
encodedQueryParam: "cursor",
expectedQueries: gourl.Values{
"limit": []string{"100"},
"active": []string{"false"},
},
isValid: false,
},
}

for _, tc := range testCases {
t.Run(tc.name, func(_ *testing.T) {
isValid := IsValidPaginationNextURL(tc.nextURL, tc.encodedQueryParam, tc.expectedQueries)
assert.Equal(tc.isValid, isValid)
})
}
}
16 changes: 16 additions & 0 deletions common/rest/request_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -137,11 +137,13 @@ func TestCachedPaginationNextURL(t *testing.T) {
name string
paginationURLs []models.PaginationURL
offset int
limit int
expectedNextURL string
}{
{
name: "return cached next URL",
offset: 200,
limit: 100,
paginationURLs: []models.PaginationURL{
{
NextURL: "/v2/example.com/stuff?limit=100",
Expand All @@ -153,6 +155,7 @@ func TestCachedPaginationNextURL(t *testing.T) {
{
name: "return empty string if cache URL cannot be determined",
offset: 40,
limit: 100,
paginationURLs: []models.PaginationURL{
{
NextURL: "/v2/example.com/stuff?limit=100",
Expand All @@ -164,9 +167,22 @@ func TestCachedPaginationNextURL(t *testing.T) {
{
name: "return empty string if no cache available",
offset: 40,
limit: 100,
paginationURLs: []models.PaginationURL{},
expectedNextURL: "",
},
{
name: "return empty string if limit in url is different than provided limit",
offset: 200,
limit: 200,
paginationURLs: []models.PaginationURL{
{
NextURL: "/v2/example.com?stuff?limit=100",
LastIndex: 100,
},
},
expectedNextURL: "",
},
}

assert := assert.New(t)
Expand Down

0 comments on commit 9ac63c3

Please sign in to comment.