github.com/opentelekomcloud/gophertelekomcloud@v0.9.3/testing/params_test.go (about) 1 package testing 2 3 import ( 4 "net/url" 5 "reflect" 6 "testing" 7 8 golangsdk "github.com/opentelekomcloud/gophertelekomcloud" 9 th "github.com/opentelekomcloud/gophertelekomcloud/testhelper" 10 ) 11 12 func TestMaybeString(t *testing.T) { 13 testString := "" 14 var expected *string 15 actual := golangsdk.MaybeString(testString) 16 th.CheckDeepEquals(t, expected, actual) 17 18 testString = "carol" 19 expected = &testString 20 actual = golangsdk.MaybeString(testString) 21 th.CheckDeepEquals(t, expected, actual) 22 } 23 24 func TestMaybeInt(t *testing.T) { 25 testInt := 0 26 var expected *int 27 actual := golangsdk.MaybeInt(testInt) 28 th.CheckDeepEquals(t, expected, actual) 29 30 testInt = 4 31 expected = &testInt 32 actual = golangsdk.MaybeInt(testInt) 33 th.CheckDeepEquals(t, expected, actual) 34 } 35 36 func TestBuildQueryString(t *testing.T) { 37 type testVar string 38 iFalse := false 39 opts := struct { 40 J int `q:"j"` 41 R string `q:"r,required"` 42 C bool `q:"c"` 43 S []string `q:"s"` 44 TS []testVar `q:"ts"` 45 TI []int `q:"ti"` 46 F *bool `q:"f"` 47 M map[string]string `q:"m"` 48 }{ 49 J: 2, 50 R: "red", 51 C: true, 52 S: []string{"one", "two", "three"}, 53 TS: []testVar{"a", "b"}, 54 TI: []int{1, 2}, 55 F: &iFalse, 56 M: map[string]string{"k1": "success1"}, 57 } 58 expected := &url.URL{RawQuery: "c=true&f=false&j=2&m=%7B%27k1%27%3A%27success1%27%7D&r=red&s=one&s=two&s=three&ti=1&ti=2&ts=a&ts=b"} 59 actual, err := golangsdk.BuildQueryString(&opts) 60 if err != nil { 61 t.Errorf("Error building query string: %v", err) 62 } 63 th.CheckDeepEquals(t, expected, actual) 64 65 opts = struct { 66 J int `q:"j"` 67 R string `q:"r,required"` 68 C bool `q:"c"` 69 S []string `q:"s"` 70 TS []testVar `q:"ts"` 71 TI []int `q:"ti"` 72 F *bool `q:"f"` 73 M map[string]string `q:"m"` 74 }{ 75 J: 2, 76 C: true, 77 } 78 _, err = golangsdk.BuildQueryString(&opts) 79 if err == nil { 80 t.Errorf("Expected error: 'Required field not set'") 81 } 82 th.CheckDeepEquals(t, expected, actual) 83 84 _, err = golangsdk.BuildQueryString(map[string]interface{}{"Number": 4}) 85 if err == nil { 86 t.Errorf("Expected error: 'Options type is not a struct'") 87 } 88 } 89 90 func TestBuildHeaders(t *testing.T) { 91 testStruct := struct { 92 Accept string `h:"Accept"` 93 Num int `h:"Number,required"` 94 Style bool `h:"Style"` 95 }{ 96 Accept: "application/json", 97 Num: 4, 98 Style: true, 99 } 100 expected := map[string]string{"Accept": "application/json", "Number": "4", "Style": "true"} 101 actual, err := golangsdk.BuildHeaders(&testStruct) 102 th.CheckNoErr(t, err) 103 th.CheckDeepEquals(t, expected, actual) 104 105 testStruct.Num = 0 106 _, err = golangsdk.BuildHeaders(&testStruct) 107 if err == nil { 108 t.Errorf("Expected error: 'Required header not set'") 109 } 110 111 _, err = golangsdk.BuildHeaders(map[string]interface{}{"Number": 4}) 112 if err == nil { 113 t.Errorf("Expected error: 'Options type is not a struct'") 114 } 115 } 116 117 func TestQueriesAreEscaped(t *testing.T) { 118 type foo struct { 119 Name string `q:"something"` 120 Shape string `q:"else"` 121 } 122 123 expected := &url.URL{RawQuery: "else=Triangl+e&something=blah%2B%3F%21%21foo"} 124 125 actual, err := golangsdk.BuildQueryString(foo{Name: "blah+?!!foo", Shape: "Triangl e"}) 126 th.AssertNoErr(t, err) 127 128 th.AssertDeepEquals(t, expected, actual) 129 } 130 131 func TestBuildRequestBody(t *testing.T) { 132 type PasswordCredentials struct { 133 Username string `json:"username" required:"true"` 134 Password string `json:"password" required:"true"` 135 } 136 137 type TokenCredentials struct { 138 ID string `json:"id,omitempty" required:"true"` 139 } 140 141 type orFields struct { 142 Filler int `json:"filler,omitempty"` 143 F1 int `json:"f1,omitempty" or:"F2"` 144 F2 int `json:"f2,omitempty" or:"F1"` 145 } 146 147 // AuthOptions wraps a golangsdk AuthOptions in order to adhere to the AuthOptionsBuilder 148 // interface. 149 type AuthOptions struct { 150 PasswordCredentials *PasswordCredentials `json:"passwordCredentials,omitempty" xor:"TokenCredentials"` 151 152 // The TenantID and TenantName fields are optional for the Identity V2 API. 153 // Some providers allow you to specify a TenantName instead of the TenantId. 154 // Some require both. Your provider's authentication policies will determine 155 // how these fields influence authentication. 156 TenantID string `json:"tenantId,omitempty"` 157 TenantName string `json:"tenantName,omitempty"` 158 159 // TokenCredentials allows users to authenticate (possibly as another user) with an 160 // authentication token ID. 161 TokenCredentials *TokenCredentials `json:"token,omitempty" xor:"PasswordCredentials"` 162 163 OrFields *orFields `json:"or_fields,omitempty"` 164 } 165 166 var successCases = []struct { 167 opts AuthOptions 168 expected map[string]interface{} 169 }{ 170 { 171 AuthOptions{ 172 PasswordCredentials: &PasswordCredentials{ 173 Username: "me", 174 Password: "swordfish", 175 }, 176 }, 177 map[string]interface{}{ 178 "auth": map[string]interface{}{ 179 "passwordCredentials": map[string]interface{}{ 180 "password": "swordfish", 181 "username": "me", 182 }, 183 }, 184 }, 185 }, 186 { 187 AuthOptions{ 188 TokenCredentials: &TokenCredentials{ 189 ID: "1234567", 190 }, 191 }, 192 map[string]interface{}{ 193 "auth": map[string]interface{}{ 194 "token": map[string]interface{}{ 195 "id": "1234567", 196 }, 197 }, 198 }, 199 }, 200 } 201 202 for _, successCase := range successCases { 203 actual, err := golangsdk.BuildRequestBody(successCase.opts, "auth") 204 th.AssertNoErr(t, err) 205 th.AssertDeepEquals(t, successCase.expected, actual) 206 } 207 208 var failCases = []struct { 209 opts AuthOptions 210 expected error 211 }{ 212 { 213 AuthOptions{ 214 TenantID: "987654321", 215 TenantName: "me", 216 }, 217 golangsdk.ErrMissingInput{}, 218 }, 219 { 220 AuthOptions{ 221 TokenCredentials: &TokenCredentials{ 222 ID: "1234567", 223 }, 224 PasswordCredentials: &PasswordCredentials{ 225 Username: "me", 226 Password: "swordfish", 227 }, 228 }, 229 golangsdk.ErrMissingInput{}, 230 }, 231 { 232 AuthOptions{ 233 PasswordCredentials: &PasswordCredentials{ 234 Password: "swordfish", 235 }, 236 }, 237 golangsdk.ErrMissingInput{}, 238 }, 239 { 240 AuthOptions{ 241 PasswordCredentials: &PasswordCredentials{ 242 Username: "me", 243 Password: "swordfish", 244 }, 245 OrFields: &orFields{ 246 Filler: 2, 247 }, 248 }, 249 golangsdk.ErrMissingInput{}, 250 }, 251 } 252 253 for _, failCase := range failCases { 254 _, err := golangsdk.BuildRequestBody(failCase.opts, "auth") 255 th.AssertDeepEquals(t, reflect.TypeOf(failCase.expected), reflect.TypeOf(err)) 256 } 257 }