minio/cmd/signature-v2_test.go
2016-09-30 14:32:13 -07:00

160 lines
4.2 KiB
Go

package cmd
import (
"fmt"
"net/http"
"net/url"
"sort"
"testing"
"time"
)
// Tests for 'func TestResourceListSorting(t *testing.T)'.
func TestResourceListSorting(t *testing.T) {
sortedResourceList := make([]string, len(resourceList))
copy(sortedResourceList, resourceList)
sort.Strings(sortedResourceList)
for i := 0; i < len(resourceList); i++ {
if resourceList[i] != sortedResourceList[i] {
t.Errorf("Expected resourceList[%d] = \"%s\", resourceList is not correctly sorted.", i, sortedResourceList[i])
break
}
}
}
// Tests validate the query encoding.
func TestQueryEncode(t *testing.T) {
testCases := []struct {
// Input.
input url.Values
// Expected result.
result string
}{
// % should be encoded as %25
{url.Values{
"key": []string{"thisisthe%url"},
}, "key=thisisthe%25url"},
// UTF-8 encoding.
{url.Values{
"key": []string{"本語"},
}, "key=%E6%9C%AC%E8%AA%9E"},
// UTF-8 encoding with ASCII.
{url.Values{
"key": []string{"本語.1"},
}, "key=%E6%9C%AC%E8%AA%9E.1"},
// Unusual ASCII characters.
{url.Values{
"key": []string{">123"},
}, "key=%3E123"},
// Fragment path characters.
{url.Values{
"key": []string{"myurl#link"},
}, "key=myurl%23link"},
// Space should be set to %20 not '+'.
{url.Values{
"key": []string{"space in url"},
}, "key=space%20in%20url"},
// '+' shouldn't be treated as space.
{url.Values{
"key": []string{"url+path"},
}, "key=url%2Bpath"},
// '/' shouldn't be treated as '/' should be percent coded.
{url.Values{
"key": []string{"url/+path"},
}, "key=url%2F%2Bpath"},
// Values is empty and empty string.
{nil, ""},
}
// Tests generated values from url encoded name.
for i, testCase := range testCases {
result := queryEncode(testCase.input)
if testCase.result != result {
t.Errorf("Test %d: Expected queryEncoded result to be \"%s\", but found it to be \"%s\" instead", i+1, testCase.result, result)
}
}
}
func TestDoesPresignedV2SignatureMatch(t *testing.T) {
root, err := newTestConfig("us-east-1")
if err != nil {
t.Fatal("Unable to initialize test config.")
}
defer removeAll(root)
now := time.Now().UTC()
testCases := []struct {
queryParams map[string]string
headers map[string]string
expected APIErrorCode
}{
// (0) Should error without a set URL query.
{
expected: ErrInvalidQueryParams,
},
// (1) Should error on an invalid access key.
{
queryParams: map[string]string{
"Expires": "60",
"Signature": "badsignature",
"AWSAccessKeyId": "Z7IXGOO6BZ0REAN1Q26I",
},
expected: ErrInvalidAccessKeyID,
},
// (2) Should error with malformed expires.
{
queryParams: map[string]string{
"Expires": "60s",
"Signature": "badsignature",
"AWSAccessKeyId": serverConfig.GetCredential().AccessKeyID,
},
expected: ErrMalformedExpires,
},
// (3) Should give an expired request if it has expired.
{
queryParams: map[string]string{
"Expires": "60",
"Signature": "badsignature",
"AWSAccessKeyId": serverConfig.GetCredential().AccessKeyID,
},
expected: ErrExpiredPresignRequest,
},
// (4) Should error when the signature does not match.
{
queryParams: map[string]string{
"Expires": fmt.Sprintf("%d", now.Unix()+60),
"Signature": "badsignature",
"AWSAccessKeyId": serverConfig.GetCredential().AccessKeyID,
},
expected: ErrSignatureDoesNotMatch,
},
}
// Run each test case individually.
for i, testCase := range testCases {
// Turn the map[string]string into map[string][]string, because Go.
query := url.Values{}
for key, value := range testCase.queryParams {
query.Set(key, value)
}
// Create a request to use.
req, e := http.NewRequest(http.MethodGet, "http://host/a/b?"+query.Encode(), nil)
if e != nil {
t.Errorf("(%d) failed to create http.Request, got %v", i, e)
}
// Do the same for the headers.
for key, value := range testCase.headers {
req.Header.Set(key, value)
}
// Check if it matches!
err := doesPresignV2SignatureMatch(req)
if err != testCase.expected {
t.Errorf("(%d) expected to get %s, instead got %s", i, niceError(testCase.expected), niceError(err))
}
}
}