forked from TrueCloudLab/restic
Update dependencies, enable pruning for vendor/
So, `dep` got an nice new feature to remove tests and non-go files from `vendor/`, and this brings the size of the vendor directory from ~300MiB down to ~20MiB. We don that now.
This commit is contained in:
parent
3422c1ca83
commit
bff635bc5f
6741 changed files with 26942 additions and 4902033 deletions
109
vendor/github.com/ncw/swift/example_test.go
generated
vendored
109
vendor/github.com/ncw/swift/example_test.go
generated
vendored
|
@ -1,109 +0,0 @@
|
|||
// Copyright...
|
||||
|
||||
// This example demonstrates opening a Connection and doing some basic operations.
|
||||
package swift_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/ncw/swift"
|
||||
)
|
||||
|
||||
func ExampleConnection() {
|
||||
// Create a v1 auth connection
|
||||
c := &swift.Connection{
|
||||
// This should be your username
|
||||
UserName: "user",
|
||||
// This should be your api key
|
||||
ApiKey: "key",
|
||||
// This should be a v1 auth url, eg
|
||||
// Rackspace US https://auth.api.rackspacecloud.com/v1.0
|
||||
// Rackspace UK https://lon.auth.api.rackspacecloud.com/v1.0
|
||||
// Memset Memstore UK https://auth.storage.memset.com/v1.0
|
||||
AuthUrl: "auth_url",
|
||||
}
|
||||
|
||||
// Authenticate
|
||||
err := c.Authenticate()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
// List all the containers
|
||||
containers, err := c.ContainerNames(nil)
|
||||
fmt.Println(containers)
|
||||
// etc...
|
||||
|
||||
// ------ or alternatively create a v2 connection ------
|
||||
|
||||
// Create a v2 auth connection
|
||||
c = &swift.Connection{
|
||||
// This is the sub user for the storage - eg "admin"
|
||||
UserName: "user",
|
||||
// This should be your api key
|
||||
ApiKey: "key",
|
||||
// This should be a version2 auth url, eg
|
||||
// Rackspace v2 https://identity.api.rackspacecloud.com/v2.0
|
||||
// Memset Memstore v2 https://auth.storage.memset.com/v2.0
|
||||
AuthUrl: "v2_auth_url",
|
||||
// Region to use - default is use first region if unset
|
||||
Region: "LON",
|
||||
// Name of the tenant - this is likely your username
|
||||
Tenant: "jim",
|
||||
}
|
||||
|
||||
// as above...
|
||||
}
|
||||
|
||||
var container string
|
||||
|
||||
func ExampleConnection_ObjectsWalk() {
|
||||
c, rollback := makeConnection(nil)
|
||||
defer rollback()
|
||||
|
||||
objects := make([]string, 0)
|
||||
err := c.ObjectsWalk(container, nil, func(opts *swift.ObjectsOpts) (interface{}, error) {
|
||||
newObjects, err := c.ObjectNames(container, opts)
|
||||
if err == nil {
|
||||
objects = append(objects, newObjects...)
|
||||
}
|
||||
return newObjects, err
|
||||
})
|
||||
fmt.Println("Found all the objects", objects, err)
|
||||
}
|
||||
|
||||
func ExampleConnection_VersionContainerCreate() {
|
||||
c, rollback := makeConnection(nil)
|
||||
defer rollback()
|
||||
|
||||
// Use the helper method to create the current and versions container.
|
||||
if err := c.VersionContainerCreate("cds", "cd-versions"); err != nil {
|
||||
fmt.Print(err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func ExampleConnection_VersionEnable() {
|
||||
c, rollback := makeConnection(nil)
|
||||
defer rollback()
|
||||
|
||||
// Build the containers manually and enable them.
|
||||
if err := c.ContainerCreate("movie-versions", nil); err != nil {
|
||||
fmt.Print(err.Error())
|
||||
}
|
||||
if err := c.ContainerCreate("movies", nil); err != nil {
|
||||
fmt.Print(err.Error())
|
||||
}
|
||||
if err := c.VersionEnable("movies", "movie-versions"); err != nil {
|
||||
fmt.Print(err.Error())
|
||||
}
|
||||
|
||||
// Access the primary container as usual with ObjectCreate(), ObjectPut(), etc.
|
||||
// etc...
|
||||
}
|
||||
|
||||
func ExampleConnection_VersionDisable() {
|
||||
c, rollback := makeConnection(nil)
|
||||
defer rollback()
|
||||
|
||||
// Disable versioning on a container. Note that this does not delete the versioning container.
|
||||
c.VersionDisable("movies")
|
||||
}
|
213
vendor/github.com/ncw/swift/meta_test.go
generated
vendored
213
vendor/github.com/ncw/swift/meta_test.go
generated
vendored
|
@ -1,213 +0,0 @@
|
|||
// Tests for swift metadata
|
||||
package swift
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestHeadersToMetadata(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestHeadersToAccountMetadata(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestHeadersToContainerMetadata(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestHeadersToObjectMetadata(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestMetadataToHeaders(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestMetadataToAccountHeaders(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestMetadataToContainerHeaders(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestMetadataToObjectHeaders(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestNsToFloatString(t *testing.T) {
|
||||
for _, d := range []struct {
|
||||
ns int64
|
||||
fs string
|
||||
}{
|
||||
{0, "0"},
|
||||
{1, "0.000000001"},
|
||||
{1000, "0.000001"},
|
||||
{1000000, "0.001"},
|
||||
{100000000, "0.1"},
|
||||
{1000000000, "1"},
|
||||
{10000000000, "10"},
|
||||
{12345678912, "12.345678912"},
|
||||
{12345678910, "12.34567891"},
|
||||
{12345678900, "12.3456789"},
|
||||
{12345678000, "12.345678"},
|
||||
{12345670000, "12.34567"},
|
||||
{12345600000, "12.3456"},
|
||||
{12345000000, "12.345"},
|
||||
{12340000000, "12.34"},
|
||||
{12300000000, "12.3"},
|
||||
{12000000000, "12"},
|
||||
{10000000000, "10"},
|
||||
{1347717491123123123, "1347717491.123123123"},
|
||||
} {
|
||||
if nsToFloatString(d.ns) != d.fs {
|
||||
t.Error("Failed", d.ns, "!=", d.fs)
|
||||
}
|
||||
if d.ns > 0 && nsToFloatString(-d.ns) != "-"+d.fs {
|
||||
t.Error("Failed on negative", d.ns, "!=", d.fs)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestFloatStringToNs(t *testing.T) {
|
||||
for _, d := range []struct {
|
||||
ns int64
|
||||
fs string
|
||||
}{
|
||||
{0, "0"},
|
||||
{0, "0."},
|
||||
{0, ".0"},
|
||||
{0, "0.0"},
|
||||
{0, "0.0000000001"},
|
||||
{1, "0.000000001"},
|
||||
{1000, "0.000001"},
|
||||
{1000000, "0.001"},
|
||||
{100000000, "0.1"},
|
||||
{100000000, "0.10"},
|
||||
{100000000, "0.1000000001"},
|
||||
{1000000000, "1"},
|
||||
{1000000000, "1."},
|
||||
{1000000000, "1.0"},
|
||||
{10000000000, "10"},
|
||||
{12345678912, "12.345678912"},
|
||||
{12345678912, "12.3456789129"},
|
||||
{12345678912, "12.34567891299"},
|
||||
{12345678910, "12.34567891"},
|
||||
{12345678900, "12.3456789"},
|
||||
{12345678000, "12.345678"},
|
||||
{12345670000, "12.34567"},
|
||||
{12345600000, "12.3456"},
|
||||
{12345000000, "12.345"},
|
||||
{12340000000, "12.34"},
|
||||
{12300000000, "12.3"},
|
||||
{12000000000, "12"},
|
||||
{10000000000, "10"},
|
||||
// This is a typical value which has more bits in than a float64
|
||||
{1347717491123123123, "1347717491.123123123"},
|
||||
} {
|
||||
ns, err := floatStringToNs(d.fs)
|
||||
if err != nil {
|
||||
t.Error("Failed conversion", err)
|
||||
}
|
||||
if ns != d.ns {
|
||||
t.Error("Failed", d.fs, "!=", d.ns, "was", ns)
|
||||
}
|
||||
if d.ns > 0 {
|
||||
ns, err := floatStringToNs("-" + d.fs)
|
||||
if err != nil {
|
||||
t.Error("Failed conversion", err)
|
||||
}
|
||||
if ns != -d.ns {
|
||||
t.Error("Failed on negative", -d.ns, "!=", "-"+d.fs)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// These are expected to produce errors
|
||||
for _, fs := range []string{
|
||||
"",
|
||||
" 1",
|
||||
"- 1",
|
||||
"- 1",
|
||||
"1.-1",
|
||||
"1.0.0",
|
||||
"1x0",
|
||||
} {
|
||||
ns, err := floatStringToNs(fs)
|
||||
if err == nil {
|
||||
t.Error("Didn't produce expected error", fs, ns)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestGetModTime(t *testing.T) {
|
||||
for _, d := range []struct {
|
||||
ns string
|
||||
t string
|
||||
}{
|
||||
{"1354040105", "2012-11-27T18:15:05Z"},
|
||||
{"1354040105.", "2012-11-27T18:15:05Z"},
|
||||
{"1354040105.0", "2012-11-27T18:15:05Z"},
|
||||
{"1354040105.000000000000", "2012-11-27T18:15:05Z"},
|
||||
{"1354040105.123", "2012-11-27T18:15:05.123Z"},
|
||||
{"1354040105.123456", "2012-11-27T18:15:05.123456Z"},
|
||||
{"1354040105.123456789", "2012-11-27T18:15:05.123456789Z"},
|
||||
{"1354040105.123456789123", "2012-11-27T18:15:05.123456789Z"},
|
||||
{"0", "1970-01-01T00:00:00.000000000Z"},
|
||||
} {
|
||||
expected, err := time.Parse(time.RFC3339, d.t)
|
||||
if err != nil {
|
||||
t.Error("Bad test", err)
|
||||
}
|
||||
m := Metadata{"mtime": d.ns}
|
||||
actual, err := m.GetModTime()
|
||||
if err != nil {
|
||||
t.Error("Parse error", err)
|
||||
}
|
||||
if !actual.Equal(expected) {
|
||||
t.Error("Expecting", expected, expected.UnixNano(), "got", actual, actual.UnixNano())
|
||||
}
|
||||
}
|
||||
for _, ns := range []string{
|
||||
"EMPTY",
|
||||
"",
|
||||
" 1",
|
||||
"- 1",
|
||||
"- 1",
|
||||
"1.-1",
|
||||
"1.0.0",
|
||||
"1x0",
|
||||
} {
|
||||
m := Metadata{}
|
||||
if ns != "EMPTY" {
|
||||
m["mtime"] = ns
|
||||
}
|
||||
actual, err := m.GetModTime()
|
||||
if err == nil {
|
||||
t.Error("Expected error not produced")
|
||||
}
|
||||
if !actual.IsZero() {
|
||||
t.Error("Expected output to be zero")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetModTime(t *testing.T) {
|
||||
for _, d := range []struct {
|
||||
ns string
|
||||
t string
|
||||
}{
|
||||
{"1354040105", "2012-11-27T18:15:05Z"},
|
||||
{"1354040105", "2012-11-27T18:15:05.000000Z"},
|
||||
{"1354040105.123", "2012-11-27T18:15:05.123Z"},
|
||||
{"1354040105.123456", "2012-11-27T18:15:05.123456Z"},
|
||||
{"1354040105.123456789", "2012-11-27T18:15:05.123456789Z"},
|
||||
{"0", "1970-01-01T00:00:00.000000000Z"},
|
||||
} {
|
||||
time, err := time.Parse(time.RFC3339, d.t)
|
||||
if err != nil {
|
||||
t.Error("Bad test", err)
|
||||
}
|
||||
m := Metadata{}
|
||||
m.SetModTime(time)
|
||||
if m["mtime"] != d.ns {
|
||||
t.Error("mtime wrong", m, "should be", d.ns)
|
||||
}
|
||||
}
|
||||
}
|
83
vendor/github.com/ncw/swift/rs/rs.go
generated
vendored
83
vendor/github.com/ncw/swift/rs/rs.go
generated
vendored
|
@ -1,83 +0,0 @@
|
|||
package rs
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"github.com/ncw/swift"
|
||||
)
|
||||
|
||||
// RsConnection is a RackSpace specific wrapper to the core swift library which
|
||||
// exposes the RackSpace CDN commands via the CDN Management URL interface.
|
||||
type RsConnection struct {
|
||||
swift.Connection
|
||||
cdnUrl string
|
||||
}
|
||||
|
||||
// manage is similar to the swift storage method, but uses the CDN Management URL for CDN specific calls.
|
||||
func (c *RsConnection) manage(p swift.RequestOpts) (resp *http.Response, headers swift.Headers, err error) {
|
||||
p.OnReAuth = func() (string, error) {
|
||||
if c.cdnUrl == "" {
|
||||
c.cdnUrl = c.Auth.CdnUrl()
|
||||
}
|
||||
if c.cdnUrl == "" {
|
||||
return "", errors.New("The X-CDN-Management-Url does not exist on the authenticated platform")
|
||||
}
|
||||
return c.cdnUrl, nil
|
||||
}
|
||||
if c.Authenticated() {
|
||||
_, err = p.OnReAuth()
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
}
|
||||
return c.Connection.Call(c.cdnUrl, p)
|
||||
}
|
||||
|
||||
// ContainerCDNEnable enables a container for public CDN usage.
|
||||
//
|
||||
// Change the default TTL of 259200 seconds (72 hours) by passing in an integer value.
|
||||
//
|
||||
// This method can be called again to change the TTL.
|
||||
func (c *RsConnection) ContainerCDNEnable(container string, ttl int) (swift.Headers, error) {
|
||||
h := swift.Headers{"X-CDN-Enabled": "true"}
|
||||
if ttl > 0 {
|
||||
h["X-TTL"] = strconv.Itoa(ttl)
|
||||
}
|
||||
|
||||
_, headers, err := c.manage(swift.RequestOpts{
|
||||
Container: container,
|
||||
Operation: "PUT",
|
||||
ErrorMap: swift.ContainerErrorMap,
|
||||
NoResponse: true,
|
||||
Headers: h,
|
||||
})
|
||||
return headers, err
|
||||
}
|
||||
|
||||
// ContainerCDNDisable disables CDN access to a container.
|
||||
func (c *RsConnection) ContainerCDNDisable(container string) error {
|
||||
h := swift.Headers{"X-CDN-Enabled": "false"}
|
||||
|
||||
_, _, err := c.manage(swift.RequestOpts{
|
||||
Container: container,
|
||||
Operation: "PUT",
|
||||
ErrorMap: swift.ContainerErrorMap,
|
||||
NoResponse: true,
|
||||
Headers: h,
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
// ContainerCDNMeta returns the CDN metadata for a container.
|
||||
func (c *RsConnection) ContainerCDNMeta(container string) (swift.Headers, error) {
|
||||
_, headers, err := c.manage(swift.RequestOpts{
|
||||
Container: container,
|
||||
Operation: "HEAD",
|
||||
ErrorMap: swift.ContainerErrorMap,
|
||||
NoResponse: true,
|
||||
Headers: swift.Headers{},
|
||||
})
|
||||
return headers, err
|
||||
}
|
96
vendor/github.com/ncw/swift/rs/rs_test.go
generated
vendored
96
vendor/github.com/ncw/swift/rs/rs_test.go
generated
vendored
|
@ -1,96 +0,0 @@
|
|||
// See swift_test.go for requirements to run this test.
|
||||
package rs_test
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/ncw/swift/rs"
|
||||
)
|
||||
|
||||
var (
|
||||
c rs.RsConnection
|
||||
)
|
||||
|
||||
const (
|
||||
CONTAINER = "GoSwiftUnitTest"
|
||||
OBJECT = "test_object"
|
||||
CONTENTS = "12345"
|
||||
CONTENT_SIZE = int64(len(CONTENTS))
|
||||
CONTENT_MD5 = "827ccb0eea8a706c4c34a16891f84e7b"
|
||||
)
|
||||
|
||||
// Test functions are run in order - this one must be first!
|
||||
func TestAuthenticate(t *testing.T) {
|
||||
UserName := os.Getenv("SWIFT_API_USER")
|
||||
ApiKey := os.Getenv("SWIFT_API_KEY")
|
||||
AuthUrl := os.Getenv("SWIFT_AUTH_URL")
|
||||
if UserName == "" || ApiKey == "" || AuthUrl == "" {
|
||||
t.Fatal("SWIFT_API_USER, SWIFT_API_KEY and SWIFT_AUTH_URL not all set")
|
||||
}
|
||||
c = rs.RsConnection{}
|
||||
c.UserName = UserName
|
||||
c.ApiKey = ApiKey
|
||||
c.AuthUrl = AuthUrl
|
||||
err := c.Authenticate()
|
||||
if err != nil {
|
||||
t.Fatal("Auth failed", err)
|
||||
}
|
||||
if !c.Authenticated() {
|
||||
t.Fatal("Not authenticated")
|
||||
}
|
||||
}
|
||||
|
||||
// Setup
|
||||
func TestContainerCreate(t *testing.T) {
|
||||
err := c.ContainerCreate(CONTAINER, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCDNEnable(t *testing.T) {
|
||||
headers, err := c.ContainerCDNEnable(CONTAINER, 0)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if _, ok := headers["X-Cdn-Uri"]; !ok {
|
||||
t.Error("Failed to enable CDN for container")
|
||||
}
|
||||
}
|
||||
|
||||
func TestOnReAuth(t *testing.T) {
|
||||
c2 := rs.RsConnection{}
|
||||
c2.UserName = c.UserName
|
||||
c2.ApiKey = c.ApiKey
|
||||
c2.AuthUrl = c.AuthUrl
|
||||
_, err := c2.ContainerCDNEnable(CONTAINER, 0)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to reauthenticate: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCDNMeta(t *testing.T) {
|
||||
headers, err := c.ContainerCDNMeta(CONTAINER)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if _, ok := headers["X-Cdn-Uri"]; !ok {
|
||||
t.Error("CDN is not enabled")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCDNDisable(t *testing.T) {
|
||||
err := c.ContainerCDNDisable(CONTAINER) // files stick in CDN until TTL expires
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
// Teardown
|
||||
func TestContainerDelete(t *testing.T) {
|
||||
err := c.ContainerDelete(CONTAINER)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
629
vendor/github.com/ncw/swift/swift_internal_test.go
generated
vendored
629
vendor/github.com/ncw/swift/swift_internal_test.go
generated
vendored
|
@ -1,629 +0,0 @@
|
|||
// This tests the swift package internals
|
||||
//
|
||||
// It does not require access to a swift server
|
||||
//
|
||||
// FIXME need to add more tests and to check URLs and parameters
|
||||
package swift
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
TEST_ADDRESS = "localhost:5324"
|
||||
AUTH_URL = "http://" + TEST_ADDRESS + "/v1.0"
|
||||
PROXY_URL = "http://" + TEST_ADDRESS + "/proxy"
|
||||
USERNAME = "test"
|
||||
APIKEY = "apikey"
|
||||
AUTH_TOKEN = "token"
|
||||
)
|
||||
|
||||
// Globals
|
||||
var (
|
||||
server *SwiftServer
|
||||
c *Connection
|
||||
)
|
||||
|
||||
// SwiftServer implements a test swift server
|
||||
type SwiftServer struct {
|
||||
t *testing.T
|
||||
checks []*Check
|
||||
}
|
||||
|
||||
// Used to check and reply to http transactions
|
||||
type Check struct {
|
||||
in Headers
|
||||
out Headers
|
||||
rx *string
|
||||
tx *string
|
||||
err *Error
|
||||
url *string
|
||||
}
|
||||
|
||||
// Add a in check
|
||||
func (check *Check) In(in Headers) *Check {
|
||||
check.in = in
|
||||
return check
|
||||
}
|
||||
|
||||
// Add an out check
|
||||
func (check *Check) Out(out Headers) *Check {
|
||||
check.out = out
|
||||
return check
|
||||
}
|
||||
|
||||
// Add an Error check
|
||||
func (check *Check) Error(StatusCode int, Text string) *Check {
|
||||
check.err = newError(StatusCode, Text)
|
||||
return check
|
||||
}
|
||||
|
||||
// Add a rx check
|
||||
func (check *Check) Rx(rx string) *Check {
|
||||
check.rx = &rx
|
||||
return check
|
||||
}
|
||||
|
||||
// Add an tx check
|
||||
func (check *Check) Tx(tx string) *Check {
|
||||
check.tx = &tx
|
||||
return check
|
||||
}
|
||||
|
||||
// Add an URL check
|
||||
func (check *Check) Url(url string) *Check {
|
||||
check.url = &url
|
||||
return check
|
||||
}
|
||||
|
||||
// Add a check
|
||||
func (s *SwiftServer) AddCheck(t *testing.T) *Check {
|
||||
server.t = t
|
||||
check := &Check{
|
||||
in: Headers{},
|
||||
out: Headers{},
|
||||
err: nil,
|
||||
}
|
||||
s.checks = append(s.checks, check)
|
||||
return check
|
||||
}
|
||||
|
||||
// Responds to a request
|
||||
func (s *SwiftServer) Respond(w http.ResponseWriter, r *http.Request) {
|
||||
if len(s.checks) < 1 {
|
||||
s.t.Fatal("Unexpected http transaction")
|
||||
}
|
||||
check := s.checks[0]
|
||||
s.checks = s.checks[1:]
|
||||
|
||||
// Check URL
|
||||
if check.url != nil && *check.url != r.URL.String() {
|
||||
s.t.Errorf("Expecting URL %q but got %q", *check.url, r.URL)
|
||||
}
|
||||
|
||||
// Check headers
|
||||
for k, v := range check.in {
|
||||
actual := r.Header.Get(k)
|
||||
if actual != v {
|
||||
s.t.Errorf("Expecting header %q=%q but got %q", k, v, actual)
|
||||
}
|
||||
}
|
||||
// Write output headers
|
||||
h := w.Header()
|
||||
for k, v := range check.out {
|
||||
h.Set(k, v)
|
||||
}
|
||||
// Return an error if required
|
||||
if check.err != nil {
|
||||
http.Error(w, check.err.Text, check.err.StatusCode)
|
||||
} else {
|
||||
if check.tx != nil {
|
||||
_, err := w.Write([]byte(*check.tx))
|
||||
if err != nil {
|
||||
s.t.Error("Write failed", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Checks to see all responses are used up
|
||||
func (s *SwiftServer) Finished() {
|
||||
if len(s.checks) > 0 {
|
||||
s.t.Error("Unused checks", s.checks)
|
||||
}
|
||||
}
|
||||
|
||||
func handle(w http.ResponseWriter, r *http.Request) {
|
||||
// out, _ := httputil.DumpRequest(r, true)
|
||||
// os.Stdout.Write(out)
|
||||
server.Respond(w, r)
|
||||
}
|
||||
|
||||
func NewSwiftServer() *SwiftServer {
|
||||
server := &SwiftServer{}
|
||||
http.HandleFunc("/", handle)
|
||||
go http.ListenAndServe(TEST_ADDRESS, nil)
|
||||
fmt.Print("Waiting for server to start ")
|
||||
for {
|
||||
fmt.Print(".")
|
||||
conn, err := net.Dial("tcp", TEST_ADDRESS)
|
||||
if err == nil {
|
||||
conn.Close()
|
||||
fmt.Println(" Started")
|
||||
break
|
||||
}
|
||||
}
|
||||
return server
|
||||
}
|
||||
|
||||
func init() {
|
||||
server = NewSwiftServer()
|
||||
c = &Connection{
|
||||
UserName: USERNAME,
|
||||
ApiKey: APIKEY,
|
||||
AuthUrl: AUTH_URL,
|
||||
}
|
||||
}
|
||||
|
||||
// Check the error is a swift error
|
||||
func checkError(t *testing.T, err error, StatusCode int, Text string) {
|
||||
if err == nil {
|
||||
t.Fatal("No error returned")
|
||||
}
|
||||
err2, ok := err.(*Error)
|
||||
if !ok {
|
||||
t.Fatal("Bad error type")
|
||||
}
|
||||
if err2.StatusCode != StatusCode {
|
||||
t.Fatalf("Bad status code, expecting %d got %d", StatusCode, err2.StatusCode)
|
||||
}
|
||||
if err2.Text != Text {
|
||||
t.Fatalf("Bad error string, expecting %q got %q", Text, err2.Text)
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME copied from swift_test.go
|
||||
func compareMaps(t *testing.T, a, b map[string]string) {
|
||||
if len(a) != len(b) {
|
||||
t.Error("Maps different sizes", a, b)
|
||||
}
|
||||
for ka, va := range a {
|
||||
if vb, ok := b[ka]; !ok || va != vb {
|
||||
t.Error("Difference in key", ka, va, b[ka])
|
||||
}
|
||||
}
|
||||
for kb, vb := range b {
|
||||
if va, ok := a[kb]; !ok || vb != va {
|
||||
t.Error("Difference in key", kb, vb, a[kb])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestInternalError(t *testing.T) {
|
||||
e := newError(404, "Not Found!")
|
||||
if e.StatusCode != 404 || e.Text != "Not Found!" {
|
||||
t.Fatal("Bad error")
|
||||
}
|
||||
if e.Error() != "Not Found!" {
|
||||
t.Fatal("Bad error")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func testCheckClose(rd io.ReadCloser, e error) (err error) {
|
||||
err = e
|
||||
defer checkClose(rd, &err)
|
||||
return
|
||||
}
|
||||
|
||||
// Make a closer which returns the error of our choice
|
||||
type myCloser struct {
|
||||
err error
|
||||
}
|
||||
|
||||
func (c *myCloser) Read([]byte) (int, error) {
|
||||
return 0, io.EOF
|
||||
}
|
||||
|
||||
func (c *myCloser) Close() error {
|
||||
return c.err
|
||||
}
|
||||
|
||||
func TestInternalCheckClose(t *testing.T) {
|
||||
if testCheckClose(&myCloser{nil}, nil) != nil {
|
||||
t.Fatal("bad 1")
|
||||
}
|
||||
if testCheckClose(&myCloser{nil}, ObjectCorrupted) != ObjectCorrupted {
|
||||
t.Fatal("bad 2")
|
||||
}
|
||||
if testCheckClose(&myCloser{ObjectNotFound}, nil) != ObjectNotFound {
|
||||
t.Fatal("bad 3")
|
||||
}
|
||||
if testCheckClose(&myCloser{ObjectNotFound}, ObjectCorrupted) != ObjectCorrupted {
|
||||
t.Fatal("bad 4")
|
||||
}
|
||||
}
|
||||
|
||||
func TestInternalParseHeaders(t *testing.T) {
|
||||
resp := &http.Response{StatusCode: 200}
|
||||
if c.parseHeaders(resp, nil) != nil {
|
||||
t.Error("Bad 1")
|
||||
}
|
||||
if c.parseHeaders(resp, authErrorMap) != nil {
|
||||
t.Error("Bad 1")
|
||||
}
|
||||
|
||||
resp = &http.Response{StatusCode: 299}
|
||||
if c.parseHeaders(resp, nil) != nil {
|
||||
t.Error("Bad 1")
|
||||
}
|
||||
|
||||
resp = &http.Response{StatusCode: 199, Status: "BOOM"}
|
||||
checkError(t, c.parseHeaders(resp, nil), 199, "HTTP Error: 199: BOOM")
|
||||
|
||||
resp = &http.Response{StatusCode: 300, Status: "BOOM"}
|
||||
checkError(t, c.parseHeaders(resp, nil), 300, "HTTP Error: 300: BOOM")
|
||||
|
||||
resp = &http.Response{StatusCode: 404, Status: "BOOM"}
|
||||
checkError(t, c.parseHeaders(resp, nil), 404, "HTTP Error: 404: BOOM")
|
||||
if c.parseHeaders(resp, ContainerErrorMap) != ContainerNotFound {
|
||||
t.Error("Bad 1")
|
||||
}
|
||||
if c.parseHeaders(resp, objectErrorMap) != ObjectNotFound {
|
||||
t.Error("Bad 1")
|
||||
}
|
||||
}
|
||||
|
||||
func TestInternalReadHeaders(t *testing.T) {
|
||||
resp := &http.Response{Header: http.Header{}}
|
||||
compareMaps(t, readHeaders(resp), Headers{})
|
||||
|
||||
resp = &http.Response{Header: http.Header{
|
||||
"one": []string{"1"},
|
||||
"two": []string{"2"},
|
||||
}}
|
||||
compareMaps(t, readHeaders(resp), Headers{"one": "1", "two": "2"})
|
||||
|
||||
// FIXME this outputs a log which we should test and check
|
||||
resp = &http.Response{Header: http.Header{
|
||||
"one": []string{"1", "11", "111"},
|
||||
"two": []string{"2"},
|
||||
}}
|
||||
compareMaps(t, readHeaders(resp), Headers{"one": "1", "two": "2"})
|
||||
}
|
||||
|
||||
func TestInternalStorage(t *testing.T) {
|
||||
// FIXME
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------
|
||||
|
||||
func TestInternalAuthenticate(t *testing.T) {
|
||||
server.AddCheck(t).In(Headers{
|
||||
"User-Agent": DefaultUserAgent,
|
||||
"X-Auth-Key": APIKEY,
|
||||
"X-Auth-User": USERNAME,
|
||||
}).Out(Headers{
|
||||
"X-Storage-Url": PROXY_URL,
|
||||
"X-Auth-Token": AUTH_TOKEN,
|
||||
}).Url("/v1.0")
|
||||
defer server.Finished()
|
||||
|
||||
err := c.Authenticate()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if c.StorageUrl != PROXY_URL {
|
||||
t.Error("Bad storage url")
|
||||
}
|
||||
if c.AuthToken != AUTH_TOKEN {
|
||||
t.Error("Bad auth token")
|
||||
}
|
||||
if !c.Authenticated() {
|
||||
t.Error("Didn't authenticate")
|
||||
}
|
||||
}
|
||||
|
||||
func TestInternalAuthenticateDenied(t *testing.T) {
|
||||
server.AddCheck(t).Error(400, "Bad request")
|
||||
server.AddCheck(t).Error(401, "DENIED")
|
||||
defer server.Finished()
|
||||
c.UnAuthenticate()
|
||||
err := c.Authenticate()
|
||||
if err != AuthorizationFailed {
|
||||
t.Fatal("Expecting AuthorizationFailed", err)
|
||||
}
|
||||
// FIXME
|
||||
// if c.Authenticated() {
|
||||
// t.Fatal("Expecting not authenticated")
|
||||
// }
|
||||
}
|
||||
|
||||
func TestInternalAuthenticateBad(t *testing.T) {
|
||||
server.AddCheck(t).Out(Headers{
|
||||
"X-Storage-Url": PROXY_URL,
|
||||
})
|
||||
defer server.Finished()
|
||||
err := c.Authenticate()
|
||||
checkError(t, err, 0, "Response didn't have storage url and auth token")
|
||||
if c.Authenticated() {
|
||||
t.Fatal("Expecting not authenticated")
|
||||
}
|
||||
|
||||
server.AddCheck(t).Out(Headers{
|
||||
"X-Auth-Token": AUTH_TOKEN,
|
||||
})
|
||||
err = c.Authenticate()
|
||||
checkError(t, err, 0, "Response didn't have storage url and auth token")
|
||||
if c.Authenticated() {
|
||||
t.Fatal("Expecting not authenticated")
|
||||
}
|
||||
|
||||
server.AddCheck(t)
|
||||
err = c.Authenticate()
|
||||
checkError(t, err, 0, "Response didn't have storage url and auth token")
|
||||
if c.Authenticated() {
|
||||
t.Fatal("Expecting not authenticated")
|
||||
}
|
||||
|
||||
server.AddCheck(t).Out(Headers{
|
||||
"X-Storage-Url": PROXY_URL,
|
||||
"X-Auth-Token": AUTH_TOKEN,
|
||||
})
|
||||
err = c.Authenticate()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !c.Authenticated() {
|
||||
t.Fatal("Expecting authenticated")
|
||||
}
|
||||
}
|
||||
|
||||
func testContainerNames(t *testing.T, rx string, expected []string) {
|
||||
server.AddCheck(t).In(Headers{
|
||||
"User-Agent": DefaultUserAgent,
|
||||
"X-Auth-Token": AUTH_TOKEN,
|
||||
}).Tx(rx).Url("/proxy")
|
||||
containers, err := c.ContainerNames(nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(containers) != len(expected) {
|
||||
t.Fatal("Wrong number of containers", len(containers), rx, len(expected), expected)
|
||||
}
|
||||
for i := range containers {
|
||||
if containers[i] != expected[i] {
|
||||
t.Error("Bad container", containers[i], expected[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
func TestInternalContainerNames(t *testing.T) {
|
||||
defer server.Finished()
|
||||
testContainerNames(t, "", []string{})
|
||||
testContainerNames(t, "one", []string{"one"})
|
||||
testContainerNames(t, "one\n", []string{"one"})
|
||||
testContainerNames(t, "one\ntwo\nthree\n", []string{"one", "two", "three"})
|
||||
}
|
||||
|
||||
func TestInternalObjectPutBytes(t *testing.T) {
|
||||
server.AddCheck(t).In(Headers{
|
||||
"User-Agent": DefaultUserAgent,
|
||||
"X-Auth-Token": AUTH_TOKEN,
|
||||
"Content-Length": "5",
|
||||
"Content-Type": "text/plain",
|
||||
}).Rx("12345")
|
||||
defer server.Finished()
|
||||
c.ObjectPutBytes("container", "object", []byte{'1', '2', '3', '4', '5'}, "text/plain")
|
||||
}
|
||||
|
||||
func TestInternalObjectPutString(t *testing.T) {
|
||||
server.AddCheck(t).In(Headers{
|
||||
"User-Agent": DefaultUserAgent,
|
||||
"X-Auth-Token": AUTH_TOKEN,
|
||||
"Content-Length": "5",
|
||||
"Content-Type": "text/plain",
|
||||
}).Rx("12345")
|
||||
defer server.Finished()
|
||||
c.ObjectPutString("container", "object", "12345", "text/plain")
|
||||
}
|
||||
|
||||
func TestSetFromEnv(t *testing.T) {
|
||||
// String
|
||||
s := ""
|
||||
|
||||
os.Setenv("POTATO", "")
|
||||
err := setFromEnv(&s, "POTATO")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
os.Setenv("POTATO", "this is a test")
|
||||
err = setFromEnv(&s, "POTATO")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if s != "this is a test" {
|
||||
t.Fatal("incorrect", s)
|
||||
}
|
||||
|
||||
os.Setenv("POTATO", "new")
|
||||
err = setFromEnv(&s, "POTATO")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if s != "this is a test" {
|
||||
t.Fatal("was reset when it shouldn't have been")
|
||||
}
|
||||
|
||||
// Integer
|
||||
i := 0
|
||||
|
||||
os.Setenv("POTATO", "42")
|
||||
err = setFromEnv(&i, "POTATO")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if i != 42 {
|
||||
t.Fatal("incorrect", i)
|
||||
}
|
||||
|
||||
os.Setenv("POTATO", "43")
|
||||
err = setFromEnv(&i, "POTATO")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if i != 42 {
|
||||
t.Fatal("was reset when it shouldn't have been")
|
||||
}
|
||||
|
||||
i = 0
|
||||
os.Setenv("POTATO", "not a number")
|
||||
err = setFromEnv(&i, "POTATO")
|
||||
if err == nil {
|
||||
t.Fatal("expecting error but didn't get one")
|
||||
}
|
||||
|
||||
// bool
|
||||
var b bool
|
||||
os.Setenv("POTATO", "1")
|
||||
err = setFromEnv(&b, "POTATO")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if b != true {
|
||||
t.Fatal("incorrect", b)
|
||||
}
|
||||
|
||||
// time.Duration
|
||||
var dt time.Duration
|
||||
os.Setenv("POTATO", "5s")
|
||||
err = setFromEnv(&dt, "POTATO")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if dt != 5*time.Second {
|
||||
t.Fatal("incorrect", dt)
|
||||
}
|
||||
|
||||
// EndpointType
|
||||
var e EndpointType
|
||||
os.Setenv("POTATO", "internal")
|
||||
err = setFromEnv(&e, "POTATO")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if e != EndpointType("internal") {
|
||||
t.Fatal("incorrect", e)
|
||||
}
|
||||
|
||||
// Unknown
|
||||
var unknown struct{}
|
||||
err = setFromEnv(&unknown, "POTATO")
|
||||
if err == nil {
|
||||
t.Fatal("expecting error")
|
||||
}
|
||||
|
||||
os.Setenv("POTATO", "")
|
||||
}
|
||||
|
||||
func TestApplyEnvironment(t *testing.T) {
|
||||
// We've tested all the setting logic above, so just do a quick test here
|
||||
c := new(Connection)
|
||||
os.Setenv("GOSWIFT_CONNECT_TIMEOUT", "100s")
|
||||
err := c.ApplyEnvironment()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if c.ConnectTimeout != 100*time.Second {
|
||||
t.Fatal("timeout incorrect", c.ConnectTimeout)
|
||||
}
|
||||
|
||||
c.ConnectTimeout = 0
|
||||
os.Setenv("GOSWIFT_CONNECT_TIMEOUT", "parse error")
|
||||
err = c.ApplyEnvironment()
|
||||
if err == nil {
|
||||
t.Fatal("expecting error")
|
||||
}
|
||||
if c.ConnectTimeout != 0 {
|
||||
t.Fatal("timeout incorrect", c.ConnectTimeout)
|
||||
}
|
||||
|
||||
os.Setenv("GOSWIFT_CONNECT_TIMEOUT", "")
|
||||
}
|
||||
|
||||
func TestApplyEnvironmentAll(t *testing.T) {
|
||||
// we do this in two phases because some of the variable set the same thing
|
||||
for phase := 1; phase <= 2; phase++ {
|
||||
c := new(Connection)
|
||||
|
||||
items := []struct {
|
||||
phase int
|
||||
result interface{}
|
||||
name string
|
||||
value string
|
||||
want interface{}
|
||||
oldValue string
|
||||
}{
|
||||
// Copied and amended from ApplyEnvironment
|
||||
// Environment variables - keep in same order as Connection
|
||||
{1, &c.Domain, "OS_USER_DOMAIN_NAME", "os_user_domain_name", "os_user_domain_name", ""},
|
||||
{1, &c.DomainId, "OS_USER_DOMAIN_ID", "os_user_domain_id", "os_user_domain_id", ""},
|
||||
{1, &c.UserName, "OS_USERNAME", "os_username", "os_username", ""},
|
||||
{1, &c.UserId, "OS_USER_ID", "os_user_id", "os_user_id", ""},
|
||||
{1, &c.ApiKey, "OS_PASSWORD", "os_password", "os_password", ""},
|
||||
{1, &c.AuthUrl, "OS_AUTH_URL", "os_auth_url", "os_auth_url", ""},
|
||||
{1, &c.Retries, "GOSWIFT_RETRIES", "4", 4, ""},
|
||||
{1, &c.UserAgent, "GOSWIFT_USER_AGENT", "goswift_user_agent", "goswift_user_agent", ""},
|
||||
{1, &c.ConnectTimeout, "GOSWIFT_CONNECT_TIMEOUT", "98s", 98 * time.Second, ""},
|
||||
{1, &c.Timeout, "GOSWIFT_TIMEOUT", "99s", 99 * time.Second, ""},
|
||||
{1, &c.Region, "OS_REGION_NAME", "os_region_name", "os_region_name", ""},
|
||||
{1, &c.AuthVersion, "ST_AUTH_VERSION", "3", 3, ""},
|
||||
{1, &c.Internal, "GOSWIFT_INTERNAL", "true", true, ""},
|
||||
{1, &c.Tenant, "OS_TENANT_NAME", "os_tenant_name", "os_tenant_name", ""},
|
||||
{2, &c.Tenant, "OS_PROJECT_NAME", "os_project_name", "os_project_name", ""},
|
||||
{1, &c.TenantId, "OS_TENANT_ID", "os_tenant_id", "os_tenant_id", ""},
|
||||
{1, &c.EndpointType, "OS_ENDPOINT_TYPE", "internal", EndpointTypeInternal, ""},
|
||||
{1, &c.TenantDomain, "OS_PROJECT_DOMAIN_NAME", "os_project_domain_name", "os_project_domain_name", ""},
|
||||
{1, &c.TenantDomainId, "OS_PROJECT_DOMAIN_ID", "os_project_domain_id", "os_project_domain_id", ""},
|
||||
{1, &c.TrustId, "OS_TRUST_ID", "os_trust_id", "os_trust_id", ""},
|
||||
{1, &c.StorageUrl, "OS_STORAGE_URL", "os_storage_url", "os_storage_url", ""},
|
||||
{1, &c.AuthToken, "OS_AUTH_TOKEN", "os_auth_token", "os_auth_token", ""},
|
||||
// v1 auth alternatives
|
||||
{2, &c.ApiKey, "ST_KEY", "st_key", "st_key", ""},
|
||||
{2, &c.UserName, "ST_USER", "st_user", "st_user", ""},
|
||||
{2, &c.AuthUrl, "ST_AUTH", "st_auth", "st_auth", ""},
|
||||
}
|
||||
|
||||
for i := range items {
|
||||
item := &items[i]
|
||||
if item.phase == phase {
|
||||
item.oldValue = os.Getenv(item.name) // save old value
|
||||
os.Setenv(item.name, item.value) // set new value
|
||||
}
|
||||
}
|
||||
|
||||
err := c.ApplyEnvironment()
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error %v", err)
|
||||
}
|
||||
|
||||
for i := range items {
|
||||
item := &items[i]
|
||||
if item.phase == phase {
|
||||
got := reflect.Indirect(reflect.ValueOf(item.result)).Interface()
|
||||
if !reflect.DeepEqual(item.want, got) {
|
||||
t.Errorf("%s: %v != %v", item.name, item.want, got)
|
||||
}
|
||||
os.Setenv(item.name, item.oldValue) // restore old value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
2911
vendor/github.com/ncw/swift/swift_test.go
generated
vendored
2911
vendor/github.com/ncw/swift/swift_test.go
generated
vendored
File diff suppressed because it is too large
Load diff
1107
vendor/github.com/ncw/swift/swifttest/server.go
generated
vendored
1107
vendor/github.com/ncw/swift/swifttest/server.go
generated
vendored
File diff suppressed because it is too large
Load diff
107
vendor/github.com/ncw/swift/timeout_reader_test.go
generated
vendored
107
vendor/github.com/ncw/swift/timeout_reader_test.go
generated
vendored
|
@ -1,107 +0,0 @@
|
|||
// This tests TimeoutReader
|
||||
|
||||
package swift
|
||||
|
||||
import (
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
// An io.ReadCloser for testing
|
||||
type testReader struct {
|
||||
sync.Mutex
|
||||
n int
|
||||
delay time.Duration
|
||||
closed bool
|
||||
}
|
||||
|
||||
// Returns n bytes with at time.Duration delay
|
||||
func newTestReader(n int, delay time.Duration) *testReader {
|
||||
return &testReader{
|
||||
n: n,
|
||||
delay: delay,
|
||||
}
|
||||
}
|
||||
|
||||
// Returns 1 byte at a time after delay
|
||||
func (t *testReader) Read(p []byte) (n int, err error) {
|
||||
if t.n <= 0 {
|
||||
return 0, io.EOF
|
||||
}
|
||||
time.Sleep(t.delay)
|
||||
p[0] = 'A'
|
||||
t.Lock()
|
||||
t.n--
|
||||
t.Unlock()
|
||||
return 1, nil
|
||||
}
|
||||
|
||||
// Close the channel
|
||||
func (t *testReader) Close() error {
|
||||
t.Lock()
|
||||
t.closed = true
|
||||
t.Unlock()
|
||||
return nil
|
||||
}
|
||||
|
||||
func TestTimeoutReaderNoTimeout(t *testing.T) {
|
||||
test := newTestReader(3, 10*time.Millisecond)
|
||||
cancelled := false
|
||||
cancel := func() {
|
||||
cancelled = true
|
||||
}
|
||||
tr := newTimeoutReader(test, 100*time.Millisecond, cancel)
|
||||
b, err := ioutil.ReadAll(tr)
|
||||
if err != nil || string(b) != "AAA" {
|
||||
t.Fatalf("Bad read %s %s", err, b)
|
||||
}
|
||||
if cancelled {
|
||||
t.Fatal("Cancelled when shouldn't have been")
|
||||
}
|
||||
if test.n != 0 {
|
||||
t.Fatal("Didn't read all")
|
||||
}
|
||||
if test.closed {
|
||||
t.Fatal("Shouldn't be closed")
|
||||
}
|
||||
tr.Close()
|
||||
if !test.closed {
|
||||
t.Fatal("Should be closed")
|
||||
}
|
||||
}
|
||||
|
||||
func TestTimeoutReaderTimeout(t *testing.T) {
|
||||
// Return those bytes slowly so we get an idle timeout
|
||||
test := newTestReader(3, 100*time.Millisecond)
|
||||
cancelled := false
|
||||
cancel := func() {
|
||||
cancelled = true
|
||||
}
|
||||
tr := newTimeoutReader(test, 10*time.Millisecond, cancel)
|
||||
_, err := ioutil.ReadAll(tr)
|
||||
if err != TimeoutError {
|
||||
t.Fatal("Expecting TimeoutError, got", err)
|
||||
}
|
||||
if !cancelled {
|
||||
t.Fatal("Not cancelled when should have been")
|
||||
}
|
||||
test.Lock()
|
||||
n := test.n
|
||||
test.Unlock()
|
||||
if n == 0 {
|
||||
t.Fatal("Read all")
|
||||
}
|
||||
if n != 3 {
|
||||
t.Fatal("Didn't read any")
|
||||
}
|
||||
if test.closed {
|
||||
t.Fatal("Shouldn't be closed")
|
||||
}
|
||||
tr.Close()
|
||||
if !test.closed {
|
||||
t.Fatal("Should be closed")
|
||||
}
|
||||
}
|
137
vendor/github.com/ncw/swift/watchdog_reader_test.go
generated
vendored
137
vendor/github.com/ncw/swift/watchdog_reader_test.go
generated
vendored
|
@ -1,137 +0,0 @@
|
|||
// This tests WatchdogReader
|
||||
|
||||
package swift
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Uses testReader from timeout_reader_test.go
|
||||
|
||||
func testWatchdogReaderTimeout(t *testing.T, initialTimeout, watchdogTimeout time.Duration, expectedTimeout bool) {
|
||||
test := newTestReader(3, 10*time.Millisecond)
|
||||
timer, firedChan := setupTimer(initialTimeout)
|
||||
wr := newWatchdogReader(test, watchdogTimeout, timer)
|
||||
b, err := ioutil.ReadAll(wr)
|
||||
if err != nil || string(b) != "AAA" {
|
||||
t.Fatalf("Bad read %s %s", err, b)
|
||||
}
|
||||
checkTimer(t, firedChan, expectedTimeout)
|
||||
}
|
||||
|
||||
func setupTimer(initialTimeout time.Duration) (timer *time.Timer, fired <-chan bool) {
|
||||
timer = time.NewTimer(initialTimeout)
|
||||
firedChan := make(chan bool)
|
||||
started := make(chan bool)
|
||||
go func() {
|
||||
started <- true
|
||||
select {
|
||||
case <-timer.C:
|
||||
firedChan <- true
|
||||
}
|
||||
}()
|
||||
<-started
|
||||
return timer, firedChan
|
||||
}
|
||||
|
||||
func checkTimer(t *testing.T, firedChan <-chan bool, expectedTimeout bool) {
|
||||
fired := false
|
||||
select {
|
||||
case fired = <-firedChan:
|
||||
default:
|
||||
}
|
||||
if expectedTimeout {
|
||||
if !fired {
|
||||
t.Fatal("Timer should have fired")
|
||||
}
|
||||
} else {
|
||||
if fired {
|
||||
t.Fatal("Timer should not have fired")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestWatchdogReaderNoTimeout(t *testing.T) {
|
||||
testWatchdogReaderTimeout(t, 100*time.Millisecond, 100*time.Millisecond, false)
|
||||
}
|
||||
|
||||
func TestWatchdogReaderTimeout(t *testing.T) {
|
||||
testWatchdogReaderTimeout(t, 5*time.Millisecond, 5*time.Millisecond, true)
|
||||
}
|
||||
|
||||
func TestWatchdogReaderNoTimeoutShortInitial(t *testing.T) {
|
||||
testWatchdogReaderTimeout(t, 5*time.Millisecond, 100*time.Millisecond, false)
|
||||
}
|
||||
|
||||
func TestWatchdogReaderTimeoutLongInitial(t *testing.T) {
|
||||
testWatchdogReaderTimeout(t, 100*time.Millisecond, 5*time.Millisecond, true)
|
||||
}
|
||||
|
||||
//slowReader simulates reading from a slow network connection by introducing a delay
|
||||
//in each Read() proportional to the amount of bytes read.
|
||||
type slowReader struct {
|
||||
reader io.Reader
|
||||
delayPerByte time.Duration
|
||||
}
|
||||
|
||||
func (r *slowReader) Read(p []byte) (n int, err error) {
|
||||
n, err = r.reader.Read(p)
|
||||
if n > 0 {
|
||||
time.Sleep(time.Duration(n) * r.delayPerByte)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
//This test verifies that the watchdogReader's timeout is not triggered by data
|
||||
//that comes in very slowly. (It should only be triggered if no data arrives at
|
||||
//all.)
|
||||
func TestWatchdogReaderOnSlowNetwork(t *testing.T) {
|
||||
byteString := make([]byte, 8*watchdogChunkSize)
|
||||
reader := &slowReader{
|
||||
reader: bytes.NewReader(byteString),
|
||||
//reading everything at once would take 100 ms, which is longer than the
|
||||
//watchdog timeout below
|
||||
delayPerByte: 200 * time.Millisecond / time.Duration(len(byteString)),
|
||||
}
|
||||
|
||||
timer, firedChan := setupTimer(10 * time.Millisecond)
|
||||
wr := newWatchdogReader(reader, 190*time.Millisecond, timer)
|
||||
|
||||
//use io.ReadFull instead of ioutil.ReadAll here because ReadAll already does
|
||||
//some chunking that would keep this testcase from failing
|
||||
b := make([]byte, len(byteString))
|
||||
n, err := io.ReadFull(wr, b)
|
||||
if err != nil || n != len(b) || !bytes.Equal(b, byteString) {
|
||||
t.Fatalf("Bad read %s %d", err, n)
|
||||
}
|
||||
|
||||
checkTimer(t, firedChan, false)
|
||||
}
|
||||
|
||||
//This test verifies that the watchdogReader's chunking logic does not mess up
|
||||
//the byte strings that are read.
|
||||
func TestWatchdogReaderValidity(t *testing.T) {
|
||||
byteString := []byte("abcdefghij")
|
||||
//make a reader with a non-standard chunk size (1 MiB would be much too huge
|
||||
//to comfortably look at the bytestring that comes out of the reader)
|
||||
wr := &watchdogReader{
|
||||
reader: bytes.NewReader(byteString),
|
||||
chunkSize: 3, //len(byteString) % chunkSize != 0 to be extra rude :)
|
||||
//don't care about the timeout stuff here
|
||||
timeout: 5 * time.Minute,
|
||||
timer: time.NewTimer(5 * time.Minute),
|
||||
}
|
||||
|
||||
b := make([]byte, len(byteString))
|
||||
n, err := io.ReadFull(wr, b)
|
||||
if err != nil || n != len(b) {
|
||||
t.Fatalf("Read error: %s", err)
|
||||
}
|
||||
if !bytes.Equal(b, byteString) {
|
||||
t.Fatalf("Bad read: %#v != %#v", string(b), string(byteString))
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue