Documentation in literate-programming-style is available at:
https://redhatinsights.github.io/insights-operator-utils/packages/http/routerutilstest.html
|
import (
"context"
"fmt"
"io"
"net/http"
"net/http/httptest"
"reflect"
"strings"
"testing"
"github.com/RedHatInsights/insights-results-aggregator-data/testdata"
types "github.com/RedHatInsights/insights-results-types"
"github.com/gorilla/mux"
"github.com/stretchr/testify/assert"
httputils "github.com/RedHatInsights/insights-operator-utils/http"
"github.com/RedHatInsights/insights-operator-utils/tests/helpers"
)
const (
cluster1ID = "715e10eb-e6ac-49b3-bd72-61734c35b6fb"
cluster2ID = "931f1495-7b16-4637-a41e-963e117bfd02"
)
func TestGetRouterPositiveIntParam_NonIntError ( t * testing . T ) {
request := mustGetRequestWithMuxVars ( t , http . MethodGet , "" , nil , map [ string ] string {
"id" : "non int" ,
} )
_ , err := httputils . GetRouterPositiveIntParam ( request , "id" )
assert . EqualError (
t ,
err ,
"Error during parsing param 'id' with value 'non int'. Error: 'unsigned integer expected'" ,
)
}
func TestGetRouterPositiveIntParam ( t * testing . T ) {
request := mustGetRequestWithMuxVars ( t , http . MethodGet , "" , nil , map [ string ] string {
"id" : "99" ,
} )
id , err := httputils . GetRouterPositiveIntParam ( request , "id" )
helpers . FailOnError ( t , err )
assert . Equal ( t , uint64 ( 99 ) , id )
}
func TestGetRouterPositiveIntParam_ZeroError ( t * testing . T ) {
request := mustGetRequestWithMuxVars ( t , http . MethodGet , "" , nil , map [ string ] string {
"id" : "0" ,
} )
_ , err := httputils . GetRouterPositiveIntParam ( request , "id" )
assert . EqualError ( t , err , "Error during parsing param 'id' with value '0'. Error: 'positive value expected'" )
}
func TestGetRouterPositiveIntParam_Missing ( t * testing . T ) {
request , err := http . NewRequest ( http . MethodGet , "organizations//clusters" , http . NoBody )
helpers . FailOnError ( t , err )
_ , err = httputils . GetRouterPositiveIntParam ( request , "test" )
assert . EqualError ( t , err , "Missing required param from request: test" )
}
|
gocyclo:ignore
|
func TestReadParam ( t * testing . T ) {
for _ , testCase := range [ ] struct {
TestName string
ParamName string
ParamValue [ ] interface { }
} {
{ TestName : "cluster" , ParamName : "cluster" , ParamValue : [ ] interface { } { testdata . ClusterName } } ,
{ TestName : "rule_id" , ParamName : "rule_id" , ParamValue : [ ] interface { } { testdata . Rule1ID } } ,
{ TestName : "error_key" , ParamName : "error_key" , ParamValue : [ ] interface { } { testdata . ErrorKey1 } } ,
{ TestName : "organization" , ParamName : "organization" , ParamValue : [ ] interface { } { testdata . OrgID } } ,
{
TestName : "organization/with_auth" ,
ParamName : "organization" ,
ParamValue : [ ] interface { } { testdata . OrgID } ,
} ,
{
TestName : "clusters" ,
ParamName : "clusters" ,
ParamValue : [ ] interface { } { testdata . ClusterName , testdata . ClusterName , testdata . ClusterName } ,
} ,
{
TestName : "organizations" ,
ParamName : "organizations" ,
ParamValue : [ ] interface { } { testdata . OrgID , testdata . OrgID } ,
} ,
{
TestName : "rule_fqdn_no_dotreport" ,
ParamName : "rule_selector" ,
ParamValue : [ ] interface { } { testdata . Rule1ID + "|" + testdata . ErrorKey1 } ,
} ,
{
TestName : "rule_fqdn_dotreport" ,
ParamName : "rule_selector" ,
ParamValue : [ ] interface { } { testdata . Rule1ID + ".report|" + testdata . ErrorKey1 } ,
} ,
} {
expectedParamValue := paramsToString ( "," , testCase . ParamValue ... )
t . Run ( testCase . TestName , func ( t * testing . T ) {
request := mustGetRequestWithMuxVars ( t , http . MethodGet , "" , nil , map [ string ] string {
testCase . ParamName : expectedParamValue ,
} )
recorder := httptest . NewRecorder ( )
var (
value string
successful bool
result interface { }
)
switch testCase . TestName {
case "cluster" :
result , successful = httputils . ReadClusterName ( recorder , request )
case "rule_id" :
result , successful = httputils . ReadRuleID ( recorder , request )
case "error_key" :
result , successful = httputils . ReadErrorKey ( recorder , request )
case "organization" :
result , successful = httputils . ReadOrganizationID ( recorder , request , false )
case "organization/with_auth" :
result , successful = httputils . ReadOrganizationID ( recorder , request , true )
case "clusters" :
var results [ ] types . ClusterName
results , successful = httputils . ReadClusterNames ( recorder , request )
result = paramsToString ( "," , results )
case "organizations" :
var results [ ] types . OrgID
results , successful = httputils . ReadOrganizationIDs ( recorder , request )
result = paramsToString ( "," , results )
case "rule_fqdn_no_dotreport" :
result , successful = httputils . ReadRuleSelector ( recorder , request )
case "rule_fqdn_dotreport" :
result , successful = httputils . ReadRuleSelector ( recorder , request )
}
assert . True ( t , successful )
value = fmt . Sprint ( result )
assert . Equal ( t , expectedParamValue , value )
} )
}
}
func TestReadClusterName_Error ( t * testing . T ) {
for _ , testCase := range [ ] struct {
TestCaseName string
Args map [ string ] string
ExpectedError string
} {
{ TestCaseName : "Missing" , Args : nil , ExpectedError : `{"status":"Missing required param from request: cluster"}` } ,
{
TestCaseName : "BadClusterName" ,
Args : map [ string ] string {
"cluster" : string ( testdata . BadClusterName ) ,
} ,
ExpectedError : `{"status":"Error during parsing param 'cluster' with value '` +
string ( testdata . BadClusterName ) + `'. Error: 'invalid UUID length: 4'"}` ,
} ,
} {
t . Run ( testCase . TestCaseName , func ( t * testing . T ) {
testReadParamError ( t , "cluster" , testCase . Args , testCase . ExpectedError )
} )
}
}
func TestReadRuleID_Error ( t * testing . T ) {
for _ , testCase := range [ ] struct {
TestCaseName string
Args map [ string ] string
ExpectedError string
} {
{ TestCaseName : "Missing" , Args : nil , ExpectedError : `{"status":"Missing required param from request: rule_id"}` } ,
{
TestCaseName : "BadRuleID" ,
Args : map [ string ] string {
"rule_id" : string ( testdata . BadRuleID ) ,
} ,
ExpectedError : `{"status":"Error during parsing param 'rule_id' with value '` +
string ( testdata . BadRuleID ) +
`'. Error: 'invalid rule ID, it must contain only from latin characters, number, underscores or dots'"}` ,
} ,
} {
t . Run ( testCase . TestCaseName , func ( t * testing . T ) {
testReadParamError ( t , "rule_id" , testCase . Args , testCase . ExpectedError )
} )
}
}
func TestReadErrorKey_Error ( t * testing . T ) {
testReadParamError (
t ,
"error_key" ,
nil ,
`{"status":"Missing required param from request: error_key"}` ,
)
}
func TestReadAndTrimRuleSelector ( t * testing . T ) {
for _ , testCase := range [ ] struct {
TestName string
ParamName string
ParamValue [ ] interface { }
} {
{
TestName : "rule_fqdn_with_dotreport" ,
ParamName : "rule_selector" ,
ParamValue : [ ] interface { } { testdata . Rule1ID + ".report|" + testdata . ErrorKey1 } ,
} ,
{
TestName : "rule_fqdn_without_dotreport" ,
ParamName : "rule_selector" ,
ParamValue : [ ] interface { } { testdata . Rule1ID + "|" + testdata . ErrorKey1 } ,
} ,
} {
expectedParamValue := string ( testdata . Rule1ID + "|" + testdata . ErrorKey1 )
t . Run ( testCase . TestName , func ( t * testing . T ) {
request := mustGetRequestWithMuxVars ( t , http . MethodGet , "" , nil , map [ string ] string {
testCase . ParamName : expectedParamValue ,
} )
recorder := httptest . NewRecorder ( )
var (
value string
successful bool
result interface { }
)
switch testCase . TestName {
case "rule_fqdn_with_dotreport" :
result , successful = httputils . ReadAndTrimRuleSelector ( recorder , request )
case "rule_fqdn_without_dotreport" :
result , successful = httputils . ReadAndTrimRuleSelector ( recorder , request )
}
assert . True ( t , successful )
value = fmt . Sprint ( result )
assert . Equal ( t , expectedParamValue , value )
} )
}
}
func TestReadRuleSelector_Error ( t * testing . T ) {
for _ , testCase := range [ ] struct {
TestCaseName string
Args map [ string ] string
ExpectedError string
} {
{ TestCaseName : "Missing" , Args : nil , ExpectedError : `{"status":"Missing required param from request: rule_selector"}` } ,
{
TestCaseName : "BadRuleSelector" ,
Args : map [ string ] string {
"rule_selector" : string ( testdata . BadRuleID ) ,
} ,
ExpectedError : `{"status":"Error during parsing param 'rule_selector' with value '` +
string ( testdata . BadRuleID ) +
`'. Error: 'Param rule_selector is not a valid rule selector (plugin_name|error_key)'"}` ,
} ,
{
TestCaseName : "RuleComponentAsRuleSelector" ,
Args : map [ string ] string {
"rule_selector" : string ( testdata . Rule1ID ) ,
} ,
ExpectedError : `{"status":"Error during parsing param 'rule_selector' with value '` +
string ( testdata . Rule1ID ) +
`'. Error: 'Param rule_selector is not a valid rule selector (plugin_name|error_key)'"}` ,
} ,
{
TestCaseName : "RuleComponentAsRuleSelector" ,
Args : map [ string ] string {
"rule_selector" : string ( testdata . Rule1ID + "|" ) ,
} ,
ExpectedError : `{"status":"Error during parsing param 'rule_selector' with value '` +
string ( testdata . Rule1ID + "|" ) +
`'. Error: 'Param rule_selector is not a valid rule selector (plugin_name|error_key)'"}` ,
} ,
} {
t . Run ( testCase . TestCaseName , func ( t * testing . T ) {
testReadParamError ( t , "rule_selector" , testCase . Args , testCase . ExpectedError )
testReadParamError ( t , "rule_selector_trimmed" , testCase . Args , testCase . ExpectedError )
} )
}
}
func TestReadOrganization_Error ( t * testing . T ) {
testReadParamError (
t ,
"organization" ,
nil ,
`{"status":"Missing required param from request: organization"}` ,
)
testReadParamError (
t ,
"organization/with_auth" ,
map [ string ] string {
"organization" : fmt . Sprint ( testdata . OrgID ) ,
} ,
`{"status":"you have no permissions to get or change info about the organization with ID ` +
fmt . Sprint ( testdata . OrgID ) + `; you can access info about organization with ID ` +
fmt . Sprint ( testdata . Org2ID ) + `"}` ,
)
}
func TestReadClusters_Error ( t * testing . T ) {
for _ , testCase := range [ ] struct {
TestCaseName string
Args map [ string ] string
ExpectedError string
} {
{ TestCaseName : "Missing" , Args : nil , ExpectedError : `{"status":"Missing required param from request: clusters"}` } ,
{
TestCaseName : "BadClusters" ,
Args : map [ string ] string {
"clusters" : string ( testdata . BadClusterName ) ,
} ,
ExpectedError : `{"status":"Error during parsing param 'cluster' with value '` +
string ( testdata . BadClusterName ) +
`'. Error: 'invalid UUID length: 4'"}` ,
} ,
} {
t . Run ( testCase . TestCaseName , func ( t * testing . T ) {
testReadParamError ( t , "clusters" , testCase . Args , testCase . ExpectedError )
} )
}
}
func TestReadOrganizations_Error ( t * testing . T ) {
const badOrgID = "non-int"
for _ , testCase := range [ ] struct {
TestCaseName string
Args map [ string ] string
ExpectedError string
} {
{
TestCaseName : "Missing" ,
Args : nil ,
ExpectedError : `{"status":"Missing required param from request: organizations"}` ,
} ,
{
TestCaseName : "BadOrganizations" ,
Args : map [ string ] string {
"organizations" : badOrgID ,
} ,
ExpectedError : `{"status":"Error during parsing param 'organizations' with value '` + badOrgID +
`'. Error: 'integer array expected'"}` ,
} ,
} {
t . Run ( testCase . TestCaseName , func ( t * testing . T ) {
testReadParamError ( t , "organizations" , testCase . Args , testCase . ExpectedError )
} )
}
}
func mustGetRequestWithMuxVars (
t * testing . T ,
method string ,
url string ,
body io . Reader ,
vars map [ string ] string ,
) * http . Request {
request , err := http . NewRequest ( method , url , body )
helpers . FailOnError ( t , err )
request = mux . SetURLVars ( request , vars )
return request
}
|
gocyclo:ignore
|
func testReadParamError ( t * testing . T , paramName string , args map [ string ] string , expectedError string ) {
request := mustGetRequestWithMuxVars ( t , http . MethodGet , "" , nil , args )
recorder := httptest . NewRecorder ( )
var successful bool
switch paramName {
case "cluster" :
_ , successful = httputils . ReadClusterName ( recorder , request )
case "rule_id" :
_ , successful = httputils . ReadRuleID ( recorder , request )
case "error_key" :
_ , successful = httputils . ReadErrorKey ( recorder , request )
case "organization" :
_ , successful = httputils . ReadOrganizationID ( recorder , request , false )
case "organization/with_auth" :
ctx := context . WithValue ( request . Context ( ) , types . ContextKeyUser , types . Identity {
AccountNumber : testdata . UserID ,
OrgID : testdata . Org2ID ,
User : types . User { UserID : testdata . UserID } ,
} )
request = request . WithContext ( ctx )
_ , successful = httputils . ReadOrganizationID ( recorder , request , true )
case "organizations" :
_ , successful = httputils . ReadOrganizationIDs ( recorder , request )
case "clusters" :
_ , successful = httputils . ReadClusterNames ( recorder , request )
case "rule_selector" :
_ , successful = httputils . ReadRuleSelector ( recorder , request )
case "rule_selector_trimmed" :
_ , successful = httputils . ReadAndTrimRuleSelector ( recorder , request )
default :
panic ( "testReadParamError is not implemented for param '" + paramName + "'" )
}
assert . False ( t , successful )
resp := recorder . Result ( )
assert . NotNil ( t , resp )
body , err := io . ReadAll ( resp . Body )
helpers . FailOnError ( t , err )
assert . Equal ( t , expectedError , strings . TrimSpace ( string ( body ) ) )
}
func paramsToString ( separator string , params ... interface { } ) string {
var unpackedParams [ ] interface { }
for _ , param := range params {
switch reflect . TypeOf ( param ) . Kind ( ) {
case reflect . Array , reflect . Slice :
s := reflect . ValueOf ( param )
for i := 0 ; i < s . Len ( ) ; i ++ {
unpackedParams = append ( unpackedParams , s . Index ( i ) . Interface ( ) )
}
default :
unpackedParams = append ( unpackedParams , param )
}
}
params = unpackedParams
var stringParams [ ] string
for _ , param := range params {
stringParams = append ( stringParams , fmt . Sprint ( param ) )
}
res := strings . Join ( stringParams , separator )
return res
}
|