aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Majewsky <majewsky@gmx.net>2018-02-07 20:45:42 +0100
committerStefan Majewsky <majewsky@gmx.net>2018-02-07 20:45:42 +0100
commit70d9fc2a699624f8fc87f1c5837241c536087373 (patch)
tree15f644c79d6012a8cd03291eff9a859e641a2606
parent99ef0307e75fecc469f63a82bb72d1b697e14fff (diff)
downloadgo-schwift-70d9fc2a699624f8fc87f1c5837241c536087373.tar.gz
increase test coverage
-rw-r--r--container_test.go48
-rw-r--r--field_test.go134
-rw-r--r--field_time.go7
-rw-r--r--generated.go6
-rw-r--r--generated.go.in2
-rw-r--r--headers_test.go43
-rw-r--r--shared_test.go108
7 files changed, 285 insertions, 63 deletions
diff --git a/container_test.go b/container_test.go
index c6e20f1..76ff037 100644
--- a/container_test.go
+++ b/container_test.go
@@ -19,15 +19,19 @@
package schwift
import (
- "crypto/rand"
- "encoding/hex"
"net/http"
"testing"
)
-func TestContainerExistence(t *testing.T) {
+func TestContainerLifecycle(t *testing.T) {
testWithAccount(t, func(a *Account) {
- c := a.Container(getRandomName())
+ containerName := getRandomName()
+ c := a.Container(containerName)
+
+ expectString(t, c.Name(), containerName)
+ if c.Account() != a {
+ t.Errorf("expected c.Account() = %#v, go %#v instead\n", a, c.Account())
+ }
exists, err := c.Exists()
expectError(t, err, "")
@@ -38,20 +42,42 @@ func TestContainerExistence(t *testing.T) {
expectBool(t, Is(err, http.StatusNotFound), true)
expectBool(t, Is(err, http.StatusNoContent), false)
+ //DELETE should be idempotent and not return success on non-existence, but
+ //OpenStack loves to be inconsistent with everything (including, notably, itself)
+ err = c.Delete(nil, nil)
+ expectError(t, err, "expected 204 response, got 404 instead: <html><h1>Not Found</h1><p>The resource could not be found.</p></html>")
+
err = c.Create(nil, nil)
expectError(t, err, "")
exists, err = c.Exists()
expectError(t, err, "")
expectBool(t, exists, true)
+
+ err = c.Delete(nil, nil)
+ expectError(t, err, "")
})
}
-func getRandomName() string {
- var buf [16]byte
- _, err := rand.Read(buf[:])
- if err != nil {
- panic(err.Error())
- }
- return hex.EncodeToString(buf[:])
+func TestContainerUpdate(t *testing.T) {
+ testWithContainer(t, func(c *Container) {
+
+ hdr, err := c.Headers()
+ expectError(t, err, "")
+ expectBool(t, hdr.ObjectCount().Exists(), true)
+ expectUint64(t, hdr.ObjectCount().Get(), 0)
+
+ hdr = make(ContainerHeaders)
+ hdr.ObjectCountQuota().Set(23)
+ hdr.BytesUsedQuota().Set(42)
+
+ err = c.Update(hdr, nil)
+ expectError(t, err, "")
+
+ hdr, err = c.Headers()
+ expectError(t, err, "")
+ expectUint64(t, hdr.BytesUsedQuota().Get(), 42)
+ expectUint64(t, hdr.ObjectCountQuota().Get(), 23)
+
+ })
}
diff --git a/field_test.go b/field_test.go
new file mode 100644
index 0000000..bea85ca
--- /dev/null
+++ b/field_test.go
@@ -0,0 +1,134 @@
+/******************************************************************************
+*
+* Copyright 2018 Stefan Majewsky <majewsky@gmx.net>
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*
+******************************************************************************/
+
+package schwift
+
+import (
+ "strconv"
+ "testing"
+)
+
+func TestFieldString(t *testing.T) {
+ hdr := make(AccountHeaders)
+ expectBool(t, hdr.TempURLKey().Exists(), false)
+ expectString(t, hdr.TempURLKey().Get(), "")
+ expectError(t, hdr.Validate(), "")
+
+ hdr["X-Account-Meta-Temp-Url-Key"] = ""
+ expectBool(t, hdr.TempURLKey().Exists(), false)
+ expectString(t, hdr.TempURLKey().Get(), "")
+ expectError(t, hdr.Validate(), "")
+
+ hdr["X-Account-Meta-Temp-Url-Key"] = "foo"
+ expectBool(t, hdr.TempURLKey().Exists(), true)
+ expectString(t, hdr.TempURLKey().Get(), "foo")
+ expectError(t, hdr.Validate(), "")
+
+ hdr.TempURLKey().Set("bar")
+ expectHeaders(t, hdr, map[string]string{
+ "X-Account-Meta-Temp-Url-Key": "bar",
+ })
+ hdr.TempURLKey().Clear()
+ expectHeaders(t, hdr, map[string]string{
+ "X-Account-Meta-Temp-Url-Key": "",
+ })
+ hdr.TempURLKey().Del()
+ expectHeaders(t, hdr, nil)
+ hdr.TempURLKey().Clear()
+ expectHeaders(t, hdr, map[string]string{
+ "X-Account-Meta-Temp-Url-Key": "",
+ })
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+func TestFieldTimestamp(t *testing.T) {
+ testWithAccount(t, func(a *Account) {
+ hdr, err := a.Headers()
+ if !expectError(t, err, "") {
+ return
+ }
+
+ expectBool(t, hdr.Timestamp().Exists(), true)
+
+ actual := float64(hdr.Timestamp().Get().UnixNano()) / 1e9
+ expected, _ := strconv.ParseFloat(hdr["X-Timestamp"], 64)
+ expectFloat64(t, actual, expected)
+ })
+
+ hdr := make(AccountHeaders)
+ expectBool(t, hdr.Timestamp().Exists(), false)
+ expectBool(t, hdr.Timestamp().Get().IsZero(), true)
+ expectError(t, hdr.Validate(), "")
+
+ hdr["X-Timestamp"] = "wtf"
+ expectBool(t, hdr.Timestamp().Exists(), true)
+ expectBool(t, hdr.Timestamp().Get().IsZero(), true)
+ expectError(t, hdr.Validate(), `Bad header X-Timestamp: strconv.ParseFloat: parsing "wtf": invalid syntax`)
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+func TestFieldUint64(t *testing.T) {
+ hdr := make(AccountHeaders)
+ expectBool(t, hdr.BytesUsedQuota().Exists(), false)
+ expectUint64(t, hdr.BytesUsedQuota().Get(), 0)
+ expectError(t, hdr.Validate(), "")
+
+ hdr["X-Account-Meta-Quota-Bytes"] = "23"
+ expectBool(t, hdr.BytesUsedQuota().Exists(), true)
+ expectUint64(t, hdr.BytesUsedQuota().Get(), 23)
+ expectError(t, hdr.Validate(), "")
+
+ hdr["X-Account-Meta-Quota-Bytes"] = "-23"
+ expectBool(t, hdr.BytesUsedQuota().Exists(), true)
+ expectUint64(t, hdr.BytesUsedQuota().Get(), 0)
+ expectError(t, hdr.Validate(), `Bad header X-Account-Meta-Quota-Bytes: strconv.ParseUint: parsing "-23": invalid syntax`)
+
+ hdr.BytesUsedQuota().Set(9001)
+ expectHeaders(t, hdr, map[string]string{
+ "X-Account-Meta-Quota-Bytes": "9001",
+ })
+ hdr.BytesUsedQuota().Clear()
+ expectHeaders(t, hdr, map[string]string{
+ "X-Account-Meta-Quota-Bytes": "",
+ })
+ hdr.BytesUsedQuota().Del()
+ expectHeaders(t, hdr, nil)
+ hdr.BytesUsedQuota().Clear()
+ expectHeaders(t, hdr, map[string]string{
+ "X-Account-Meta-Quota-Bytes": "",
+ })
+}
+
+func TestFieldUint64Readonly(t *testing.T) {
+ hdr := make(AccountHeaders)
+ expectBool(t, hdr.BytesUsed().Exists(), false)
+ expectUint64(t, hdr.BytesUsed().Get(), 0)
+ expectError(t, hdr.Validate(), "")
+
+ hdr["X-Account-Bytes-Used"] = "23"
+ expectBool(t, hdr.BytesUsed().Exists(), true)
+ expectUint64(t, hdr.BytesUsed().Get(), 23)
+ expectError(t, hdr.Validate(), "")
+
+ hdr["X-Account-Bytes-Used"] = "-23"
+ expectBool(t, hdr.BytesUsed().Exists(), true)
+ expectUint64(t, hdr.BytesUsed().Get(), 0)
+ expectError(t, hdr.Validate(), `Bad header X-Account-Bytes-Used: strconv.ParseUint: parsing "-23": invalid syntax`)
+}
diff --git a/field_time.go b/field_time.go
index d8a1776..25a2c1e 100644
--- a/field_time.go
+++ b/field_time.go
@@ -19,7 +19,6 @@
package schwift
import (
- "math"
"strconv"
"time"
)
@@ -58,11 +57,7 @@ func (f FieldUnixTimeReadonly) Get() time.Time {
if err != nil {
return time.Time{}
}
- seconds := math.Floor(v)
- return time.Unix(
- int64(seconds),
- int64(1e9*(v-seconds)),
- )
+ return time.Unix(0, int64(1e9*v))
}
func (f FieldUnixTimeReadonly) validate() error {
diff --git a/generated.go b/generated.go
index 60b5a46..31233ea 100644
--- a/generated.go
+++ b/generated.go
@@ -61,7 +61,7 @@ func (h AccountHeaders) Validate() error {
if err := h.Metadata().validate(); err != nil {
return err
}
- if err := h.QuotaBytes().validate(); err != nil {
+ if err := h.BytesUsedQuota().validate(); err != nil {
return err
}
if err := h.TempURLKey2().validate(); err != nil {
@@ -94,8 +94,8 @@ func (h AccountHeaders) Metadata() FieldMetadata {
return FieldMetadata{h, "X-Account-Meta-"}
}
-//QuotaBytes provides type-safe access to X-Account-Meta-Quota-Bytes headers.
-func (h AccountHeaders) QuotaBytes() FieldUint64 {
+//BytesUsedQuota provides type-safe access to X-Account-Meta-Quota-Bytes headers.
+func (h AccountHeaders) BytesUsedQuota() FieldUint64 {
return FieldUint64{h, "X-Account-Meta-Quota-Bytes"}
}
diff --git a/generated.go.in b/generated.go.in
index 808c950..680b551 100644
--- a/generated.go.in
+++ b/generated.go.in
@@ -4,7 +4,7 @@
{ "Header": "X-Account-Bytes-Used", "Attribute": "BytesUsed", "Type": "Uint64Readonly" },
{ "Header": "X-Account-Container-Count", "Attribute": "ContainerCount", "Type": "Uint64Readonly" },
{ "Header": "X-Account-Meta-", "Attribute": "Metadata", "Type": "Metadata" },
- { "Header": "X-Account-Meta-Quota-Bytes", "Attribute": "QuotaBytes", "Type": "Uint64" },
+ { "Header": "X-Account-Meta-Quota-Bytes", "Attribute": "BytesUsedQuota", "Type": "Uint64" },
{ "Header": "X-Account-Meta-Temp-URL-Key-2", "Attribute": "TempURLKey2", "Type": "String" },
{ "Header": "X-Account-Meta-Temp-URL-Key", "Attribute": "TempURLKey", "Type": "String" },
{ "Header": "X-Account-Object-Count", "Attribute": "ObjectCount", "Type": "Uint64Readonly" },
diff --git a/headers_test.go b/headers_test.go
index f8b604c..d068623 100644
--- a/headers_test.go
+++ b/headers_test.go
@@ -36,7 +36,7 @@ func TestParseAccountHeadersSuccess(t *testing.T) {
expectUint64(t, headers.BytesUsed().Get(), 1234)
expectUint64(t, headers.ContainerCount().Get(), 23)
expectUint64(t, headers.ObjectCount().Get(), 42)
- expectUint64(t, headers.QuotaBytes().Get(), 1048576)
+ expectUint64(t, headers.BytesUsedQuota().Get(), 1048576)
expectString(t, headers.Metadata().Get("foo"), "bar")
expectString(t, headers.Metadata().Get("Foo"), "bar")
@@ -44,44 +44,3 @@ func TestParseAccountHeadersSuccess(t *testing.T) {
}
//TODO TestParseAccountHeadersError
-
-func expectBool(t *testing.T, actual bool, expected bool) {
- t.Helper()
- if actual != expected {
- t.Errorf("expected value %#v, got %#v instead\n", expected, actual)
- }
-}
-
-func expectUint64(t *testing.T, actual uint64, expected uint64) {
- t.Helper()
- if actual != expected {
- t.Errorf("expected value %d, got %d instead\n", expected, actual)
- }
-}
-
-func expectString(t *testing.T, actual string, expected string) {
- t.Helper()
- if actual != expected {
- t.Errorf("expected value %q, got %q instead\n", expected, actual)
- }
-}
-
-func expectError(t *testing.T, actual error, expected string) (ok bool) {
- t.Helper()
- if actual == nil {
- if expected != "" {
- t.Errorf("expected error %q, got no error\n", expected)
- return false
- }
- } else {
- if expected == "" {
- t.Errorf("expected no error, got %q\n", actual.Error())
- return false
- } else if expected != actual.Error() {
- t.Errorf("expected error %q, got %q instead\n", expected, actual.Error())
- return false
- }
- }
-
- return true
-}
diff --git a/shared_test.go b/shared_test.go
index bc67320..04481d4 100644
--- a/shared_test.go
+++ b/shared_test.go
@@ -19,6 +19,9 @@
package schwift
import (
+ "crypto/rand"
+ "encoding/hex"
+ "math"
"os"
"testing"
@@ -72,3 +75,108 @@ func testWithAccount(t *testing.T, testCode func(a *Account)) {
}
testCode(account)
}
+
+func testWithContainer(t *testing.T, testCode func(c *Container)) {
+ testWithAccount(t, func(a *Account) {
+ containerName := getRandomName()
+ container, err := a.Container(containerName).EnsureExists()
+ expectError(t, err, "")
+
+ testCode(container)
+
+ //cleanup
+ exists, err := container.Exists()
+ expectError(t, err, "")
+ if exists {
+ err = container.Delete(nil, nil)
+ expectError(t, err, "")
+ }
+ })
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+func getRandomName() string {
+ var buf [16]byte
+ _, err := rand.Read(buf[:])
+ if err != nil {
+ panic(err.Error())
+ }
+ return hex.EncodeToString(buf[:])
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+func expectBool(t *testing.T, actual bool, expected bool) {
+ t.Helper()
+ if actual != expected {
+ t.Errorf("expected value %#v, got %#v instead\n", expected, actual)
+ }
+}
+
+func expectFloat64(t *testing.T, actual float64, expected float64) {
+ t.Helper()
+ if math.Abs((actual-expected)/expected) > 1e-8 {
+ t.Errorf("expected value %g, got %g instead\n", expected, actual)
+ }
+}
+
+func expectUint64(t *testing.T, actual uint64, expected uint64) {
+ t.Helper()
+ if actual != expected {
+ t.Errorf("expected value %d, got %d instead\n", expected, actual)
+ }
+}
+
+func expectString(t *testing.T, actual string, expected string) {
+ t.Helper()
+ if actual != expected {
+ t.Errorf("expected value %q, got %q instead\n", expected, actual)
+ }
+}
+
+func expectError(t *testing.T, actual error, expected string) (ok bool) {
+ t.Helper()
+ if actual == nil {
+ if expected != "" {
+ t.Errorf("expected error %q, got no error\n", expected)
+ return false
+ }
+ } else {
+ if expected == "" {
+ t.Errorf("expected no error, got %q\n", actual.Error())
+ return false
+ } else if expected != actual.Error() {
+ t.Errorf("expected error %q, got %q instead\n", expected, actual.Error())
+ return false
+ }
+ }
+
+ return true
+}
+
+func expectHeaders(t *testing.T, actual map[string]string, expected map[string]string) {
+ t.Helper()
+ reported := make(map[string]bool)
+
+ for k, av := range actual {
+ ev, exists := expected[k]
+ if !exists {
+ ev = "<not set>"
+ }
+ if av != ev {
+ t.Errorf(`expected "%s: %s", got "%s: %s" instead`, k, ev, k, av)
+ reported[k] = true
+ }
+ }
+
+ for k, ev := range expected {
+ av, exists := actual[k]
+ if !exists {
+ av = "<not set>"
+ }
+ if av != ev && !reported[k] {
+ t.Errorf(`expected "%s: %s", got "%s: %s" instead`, k, ev, k, av)
+ }
+ }
+}