diff --git a/CHANGELOG.md b/CHANGELOG.md
index f97cef8..80d81f3 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,11 @@
# Tideland Go REST Server Library
+## 2017-02-10
+
+- Extended *Request* and *Response* of *restaudit* with some
+ convenience methods for easier testing
+- Adopted *restaudit* changes in *rest* tests
+
## 2017-01-19
- Renamed type *Query* to *Values*
diff --git a/LICENSE b/LICENSE
index 6ff86e4..0801e5d 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,4 +1,4 @@
-Copyright (c) 2009-2016, Frank Mueller / Tideland / Oldenburg / Germany
+Copyright (c) 2009-2017, Frank Mueller / Tideland / Oldenburg / Germany
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
diff --git a/README.md b/README.md
index 15cdac9..71bf50b 100644
--- a/README.md
+++ b/README.md
@@ -14,35 +14,35 @@ I hope you like it. ;)
## Version
-Version 2.10.0
+Version 2.11.0
## Packages
-#### REST
+### REST
RESTful web request handling.
[![GoDoc](https://godoc.org/github.com/tideland/gorest/rest?status.svg)](https://godoc.org/github.com/tideland/gorest/rest)
-#### Request
+### Request
Convenient client requests to RESTful web services.
[![GoDoc](https://godoc.org/github.com/tideland/gorest/request?status.svg)](https://godoc.org/github.com/tideland/gorest/request)
-#### Handlers
+### Handlers
Some general purpose handlers for the library.
[![GoDoc](https://godoc.org/github.com/tideland/gorest/handlers?status.svg)](https://godoc.org/github.com/tideland/gorest/handlers)
-#### JSON Web Token
+### JSON Web Token
JWT package for secure authentication and information exchange like claims.
[![GoDoc](https://godoc.org/github.com/tideland/gorest/jwt?status.svg)](https://godoc.org/github.com/tideland/gorest/jwt)
-#### REST Audit
+### REST Audit
Helpers for the unit tests of the Go REST Server Library.
diff --git a/handlers/audit.go b/handlers/audit.go
index fd49bf9..2ab2a04 100644
--- a/handlers/audit.go
+++ b/handlers/audit.go
@@ -1,6 +1,6 @@
// Tideland Go REST Server Library - Handlers - Audit Handler
//
-// Copyright (C) 2009-2016 Frank Mueller / Tideland / Oldenburg / Germany
+// Copyright (C) 2009-2017 Frank Mueller / Tideland / Oldenburg / Germany
//
// All rights reserved. Use of this source code is governed
// by the new BSD license.
diff --git a/handlers/doc.go b/handlers/doc.go
index 96ab2cc..37ec7af 100644
--- a/handlers/doc.go
+++ b/handlers/doc.go
@@ -1,11 +1,11 @@
// Tideland Go REST Server Library - Handlers
//
-// Copyright (C) 2009-2016 Frank Mueller / Tideland / Oldenburg / Germany
+// Copyright (C) 2009-2017 Frank Mueller / Tideland / Oldenburg / Germany
//
// All rights reserved. Use of this source code is governed
// by the new BSD license.
-// The Tideland Go REST Server Library handlers package defines
+// Package handlers of the Tideland Go REST Server Library implements
// some initial resource handlers to integrate into own solutions.
package handlers
diff --git a/handlers/errors.go b/handlers/errors.go
index 4e9fb51..f37b7cf 100644
--- a/handlers/errors.go
+++ b/handlers/errors.go
@@ -1,6 +1,6 @@
// Tideland Go REST Server Library - Handlers - Errors
//
-// Copyright (C) 2009-2016 Frank Mueller / Tideland / Oldenburg / Germany
+// Copyright (C) 2009-2017 Frank Mueller / Tideland / Oldenburg / Germany
//
// All rights reserved. Use of this source code is governed
// by the new BSD license.
diff --git a/handlers/fileserve.go b/handlers/fileserve.go
index 39bce5e..92b6530 100644
--- a/handlers/fileserve.go
+++ b/handlers/fileserve.go
@@ -1,6 +1,6 @@
// Tideland Go REST Server Library - Handlers - File Serve
//
-// Copyright (C) 2009-2016 Frank Mueller / Tideland / Oldenburg / Germany
+// Copyright (C) 2009-2017 Frank Mueller / Tideland / Oldenburg / Germany
//
// All rights reserved. Use of this source code is governed
// by the new BSD license.
diff --git a/handlers/fileupload.go b/handlers/fileupload.go
index 79f2696..195f5b7 100644
--- a/handlers/fileupload.go
+++ b/handlers/fileupload.go
@@ -1,6 +1,6 @@
// Tideland Go REST Server Library - Handlers - File Upload
//
-// Copyright (C) 2009-2016 Frank Mueller / Tideland / Oldenburg / Germany
+// Copyright (C) 2009-2017 Frank Mueller / Tideland / Oldenburg / Germany
//
// All rights reserved. Use of this source code is governed
// by the new BSD license.
diff --git a/handlers/handlers_test.go b/handlers/handlers_test.go
index 8f86674..2034978 100644
--- a/handlers/handlers_test.go
+++ b/handlers/handlers_test.go
@@ -1,6 +1,6 @@
// Tideland Go REST Server Library - Handlers - Unit Tests
//
-// Copyright (C) 2009-2016 Frank Mueller / Tideland / Oldenburg / Germany
+// Copyright (C) 2009-2017 Frank Mueller / Tideland / Oldenburg / Germany
//
// All rights reserved. Use of this source code is governed
// by the new BSD license.
diff --git a/handlers/jwtauth.go b/handlers/jwtauth.go
index cb07a52..4d5b2cb 100644
--- a/handlers/jwtauth.go
+++ b/handlers/jwtauth.go
@@ -1,6 +1,6 @@
// Tideland Go REST Server Library - Handlers - JWT Authorization
//
-// Copyright (C) 2009-2016 Frank Mueller / Tideland / Oldenburg / Germany
+// Copyright (C) 2009-2017 Frank Mueller / Tideland / Oldenburg / Germany
//
// All rights reserved. Use of this source code is governed
// by the new BSD license.
diff --git a/handlers/wrapper.go b/handlers/wrapper.go
index 6561e28..2336520 100644
--- a/handlers/wrapper.go
+++ b/handlers/wrapper.go
@@ -1,6 +1,6 @@
// Tideland Go REST Server Library - Handlers - Wrapper
//
-// Copyright (C) 2009-2016 Frank Mueller / Tideland / Oldenburg / Germany
+// Copyright (C) 2009-2017 Frank Mueller / Tideland / Oldenburg / Germany
//
// All rights reserved. Use of this source code is governed
// by the new BSD license.
diff --git a/jwt/algorithm.go b/jwt/algorithm.go
index 100a0a4..76dfe84 100644
--- a/jwt/algorithm.go
+++ b/jwt/algorithm.go
@@ -1,6 +1,6 @@
// Tideland Go REST Server Library - JSON Web Token - Algorithm
//
-// Copyright (C) 2016 Frank Mueller / Tideland / Oldenburg / Germany
+// Copyright (C) 2016-2017 Frank Mueller / Tideland / Oldenburg / Germany
//
// All rights reserved. Use of this source code is governed
// by the new BSD license.
diff --git a/jwt/cache.go b/jwt/cache.go
index 2ec224e..3a58c1c 100644
--- a/jwt/cache.go
+++ b/jwt/cache.go
@@ -1,6 +1,6 @@
// Tideland Go REST Server Library - JSON Web Token - Cache
//
-// Copyright (C) 2016 Frank Mueller / Tideland / Oldenburg / Germany
+// Copyright (C) 2016-2017 Frank Mueller / Tideland / Oldenburg / Germany
//
// All rights reserved. Use of this source code is governed
// by the new BSD license.
diff --git a/jwt/cache_test.go b/jwt/cache_test.go
index c3b5435..35fdea1 100644
--- a/jwt/cache_test.go
+++ b/jwt/cache_test.go
@@ -1,6 +1,6 @@
// Tideland Go REST Server Library - JSON Web Token - Unit Tests
//
-// Copyright (C) 2016 Frank Mueller / Tideland / Oldenburg / Germany
+// Copyright (C) 2016-2017 Frank Mueller / Tideland / Oldenburg / Germany
//
// All rights reserved. Use of this source code is governed
// by the new BSD license.
diff --git a/jwt/claims.go b/jwt/claims.go
index fb2de23..343c4f1 100644
--- a/jwt/claims.go
+++ b/jwt/claims.go
@@ -1,6 +1,6 @@
// Tideland Go REST Server Library - JSON Web Token - Claims
//
-// Copyright (C) 2016 Frank Mueller / Tideland / Oldenburg / Germany
+// Copyright (C) 2016-2017 Frank Mueller / Tideland / Oldenburg / Germany
//
// All rights reserved. Use of this source code is governed
// by the new BSD license.
diff --git a/jwt/claims_test.go b/jwt/claims_test.go
index d3a2a6e..d07e3b2 100644
--- a/jwt/claims_test.go
+++ b/jwt/claims_test.go
@@ -1,6 +1,6 @@
// Tideland Go REST Server Library - JSON Web Token - Unit Tests
//
-// Copyright (C) 2016 Frank Mueller / Tideland / Oldenburg / Germany
+// Copyright (C) 2016-2017 Frank Mueller / Tideland / Oldenburg / Germany
//
// All rights reserved. Use of this source code is governed
// by the new BSD license.
diff --git a/jwt/doc.go b/jwt/doc.go
index 881d1d2..4ee79e8 100644
--- a/jwt/doc.go
+++ b/jwt/doc.go
@@ -1,11 +1,11 @@
// Tideland Go REST Server Library - JSON Web Token
//
-// Copyright (C) 2016 Frank Mueller / Tideland / Oldenburg / Germany
+// Copyright (C) 2016-2017 Frank Mueller / Tideland / Oldenburg / Germany
//
// All rights reserved. Use of this source code is governed
// by the new BSD license.
-// The Tideland Go REST Server Library jwt provides the generation,
+// Package jwt of the Tideland Go REST Server Library provides the generation,
// verification, and analyzing of JSON Web Tokens.
package jwt
diff --git a/request/doc.go b/request/doc.go
index 33d3429..b814174 100644
--- a/request/doc.go
+++ b/request/doc.go
@@ -1,12 +1,13 @@
// Tideland Go REST Server Library - Request
//
-// Copyright (C) 2009-2016 Frank Mueller / Tideland / Oldenburg / Germany
+// Copyright (C) 2009-2017 Frank Mueller / Tideland / Oldenburg / Germany
//
// All rights reserved. Use of this source code is governed
// by the new BSD license.
-// The request package provides a simple way to handle cross-server
-// requests in the Tideland REST ecosystem.
+// Package request of the Tideland Go REST Server Library provides
+// a simple way to handle cross-server requests in the Tideland
+// REST ecosystem.
package request
//--------------------
diff --git a/request/errors.go b/request/errors.go
index e749079..afd1979 100644
--- a/request/errors.go
+++ b/request/errors.go
@@ -1,6 +1,6 @@
// Tideland Go REST Server Library - Request - Errors
//
-// Copyright (C) 2009-2016 Frank Mueller / Tideland / Oldenburg / Germany
+// Copyright (C) 2009-2017 Frank Mueller / Tideland / Oldenburg / Germany
//
// All rights reserved. Use of this source code is governed
// by the new BSD license.
diff --git a/request/request.go b/request/request.go
index 4136c8f..bc421a9 100644
--- a/request/request.go
+++ b/request/request.go
@@ -1,6 +1,6 @@
// Tideland Go REST Server Library - Request
//
-// Copyright (C) 2009-2016 Frank Mueller / Tideland / Oldenburg / Germany
+// Copyright (C) 2009-2017 Frank Mueller / Tideland / Oldenburg / Germany
//
// All rights reserved. Use of this source code is governed
// by the new BSD license.
diff --git a/request/request_test.go b/request/request_test.go
index cc4856c..bdad5a4 100644
--- a/request/request_test.go
+++ b/request/request_test.go
@@ -1,6 +1,6 @@
// Tideland Go REST Server Library - Request - Unit Tests
//
-// Copyright (C) 2009-2016 Frank Mueller / Tideland / Oldenburg / Germany
+// Copyright (C) 2009-2017 Frank Mueller / Tideland / Oldenburg / Germany
//
// All rights reserved. Use of this source code is governed
// by the new BSD license.
diff --git a/rest/doc.go b/rest/doc.go
index e240f93..9f8af58 100644
--- a/rest/doc.go
+++ b/rest/doc.go
@@ -5,8 +5,8 @@
// All rights reserved. Use of this source code is governed
// by the new BSD license.
-// The Tideland Go REST Server Library provides the package rest for the
-// implementation of servers with a RESTful API. The business has to
+// Package rest of the Tideland Go REST Server Library provides types for
+// the implementation of servers with a RESTful API. The business has to
// be implemented in types fullfilling the ResourceHandler interface.
// This basic interface only allows the initialization of the handler.
// More interesting are the other interfaces like GetResourceHandler
diff --git a/rest/rest_test.go b/rest/rest_test.go
index 5d4c2ae..efa5e88 100644
--- a/rest/rest_test.go
+++ b/rest/rest_test.go
@@ -12,11 +12,7 @@ package rest_test
//--------------------
import (
- "bytes"
"context"
- "encoding/gob"
- "encoding/json"
- "encoding/xml"
"testing"
"github.com/tideland/golib/audit"
@@ -50,17 +46,13 @@ func TestGetJSON(t *testing.T) {
err := mux.Register("test", "json", NewTestHandler("json", assert))
assert.Nil(err)
// Perform test requests.
- resp := ts.DoRequest(&restaudit.Request{
- Method: "GET",
- Path: "/base/test/json/4711?foo=0815",
- Header: restaudit.KeyValues{"Accept": "application/json"},
- })
- var data TestRequestData
- err = json.Unmarshal(resp.Body, &data)
- assert.Nil(err)
- assert.Equal(data.ResourceID, "4711")
- assert.Equal(data.Query, "0815")
- assert.Equal(data.Context, "foo")
+ req := restaudit.NewRequest("GET", "/base/test/json/4711?foo=0815")
+ req.AddHeader(restaudit.HeaderAccept, restaudit.ApplicationJSON)
+ resp := ts.DoRequest(req)
+ resp.AssertStatus(assert, 200)
+ resp.AssertContentMatch(assert, `.*"ResourceID":"4711".*`)
+ resp.AssertContentMatch(assert, `.*"Query":"0815".*`)
+ resp.AssertContentMatch(assert, `.*"Context":"foo".*`)
}
// TestPutJSON tests the PUT command with a JSON payload and result.
@@ -73,18 +65,14 @@ func TestPutJSON(t *testing.T) {
err := mux.Register("test", "json", NewTestHandler("json", assert))
assert.Nil(err)
// Perform test requests.
+ req := restaudit.NewRequest("PUT", "/base/test/json/4711")
reqData := TestRequestData{"foo", "bar", "4711", "0815", ""}
- reqBuf, _ := json.Marshal(reqData)
- resp := ts.DoRequest(&restaudit.Request{
- Method: "PUT",
- Path: "/base/test/json/4711",
- Header: restaudit.KeyValues{"Content-Type": "application/json", "Accept": "application/json"},
- Body: reqBuf,
- })
- var recvData TestRequestData
- err = json.Unmarshal(resp.Body, &recvData)
- assert.Nil(err)
- assert.Equal(recvData, reqData)
+ req.SetContent(assert, restaudit.ApplicationJSON, reqData)
+ resp := ts.DoRequest(req)
+ resp.AssertStatus(assert, 200)
+ respData := TestRequestData{}
+ resp.AssertContent(assert, &respData)
+ assert.Equal(respData, reqData)
}
// TestGetXML tests the GET command with an XML result.
@@ -97,12 +85,11 @@ func TestGetXML(t *testing.T) {
err := mux.Register("test", "xml", NewTestHandler("xml", assert))
assert.Nil(err)
// Perform test requests.
- resp := ts.DoRequest(&restaudit.Request{
- Method: "GET",
- Path: "/base/test/xml/4711",
- Header: restaudit.KeyValues{"Accept": "application/xml"},
- })
- assert.Substring("4711", string(resp.Body))
+ req := restaudit.NewRequest("GET", "/base/test/xml/4711")
+ req.AddHeader(restaudit.HeaderAccept, restaudit.ApplicationXML)
+ resp := ts.DoRequest(req)
+ resp.AssertStatus(assert, 200)
+ resp.AssertContentMatch(assert, `.*4711.*`)
}
// TestPutXML tests the PUT command with a XML payload and result.
@@ -115,18 +102,14 @@ func TestPutXML(t *testing.T) {
err := mux.Register("test", "xml", NewTestHandler("xml", assert))
assert.Nil(err)
// Perform test requests.
+ req := restaudit.NewRequest("PUT", "/base/test/xml/4711")
reqData := TestRequestData{"foo", "bar", "4711", "0815", ""}
- reqBuf, _ := xml.Marshal(reqData)
- resp := ts.DoRequest(&restaudit.Request{
- Method: "PUT",
- Path: "/base/test/xml/4711",
- Header: restaudit.KeyValues{"Content-Type": "application/xml", "Accept": "application/xml"},
- Body: reqBuf,
- })
- var recvData TestRequestData
- err = xml.Unmarshal(resp.Body, &recvData)
- assert.Nil(err)
- assert.Equal(recvData, reqData)
+ req.SetContent(assert, restaudit.ApplicationXML, reqData)
+ resp := ts.DoRequest(req)
+ resp.AssertStatus(assert, 200)
+ respData := TestRequestData{}
+ resp.AssertContent(assert, &respData)
+ assert.Equal(respData, reqData)
}
// TestPutGOB tests the PUT command with a GOB payload and result.
@@ -139,21 +122,14 @@ func TestPutGOB(t *testing.T) {
err := mux.Register("test", "gob", NewTestHandler("putgob", assert))
assert.Nil(err)
// Perform test requests.
+ req := restaudit.NewRequest("POST", "/base/test/gob")
reqData := TestCounterData{"test", 4711}
- reqBuf := new(bytes.Buffer)
- err = gob.NewEncoder(reqBuf).Encode(reqData)
- assert.Nil(err, "GOB encode.")
- resp := ts.DoRequest(&restaudit.Request{
- Method: "POST",
- Path: "/base/test/gob",
- Header: restaudit.KeyValues{"Content-Type": "application/vnd.tideland.gob"},
- Body: reqBuf.Bytes(),
- })
- var respData TestCounterData
- err = gob.NewDecoder(bytes.NewBuffer(resp.Body)).Decode(&respData)
- assert.Nil(err)
- assert.Equal(respData.ID, "test")
- assert.Equal(respData.Count, int64(4711))
+ req.SetContent(assert, restaudit.ApplicationGOB, reqData)
+ resp := ts.DoRequest(req)
+ resp.AssertStatus(assert, 200)
+ respData := TestCounterData{}
+ resp.AssertContent(assert, &respData)
+ assert.Equal(respData, reqData)
}
// TestLongPath tests the setting of long path tail as resource ID.
@@ -166,11 +142,9 @@ func TestLongPath(t *testing.T) {
err := mux.Register("content", "blog", NewTestHandler("default", assert))
assert.Nil(err)
// Perform test requests.
- resp := ts.DoRequest(&restaudit.Request{
- Method: "GET",
- Path: "/base/content/blog/2014/09/30/just-a-test",
- })
- assert.Substring("
Resource ID: 2014/09/30/just-a-test", string(resp.Body))
+ req := restaudit.NewRequest("GET", "/base/content/blog/2014/09/30/just-a-test")
+ resp := ts.DoRequest(req)
+ resp.AssertContentMatch(assert, `.*Resource ID: 2014/09/30/just-a-test.*`)
}
// TestFallbackDefault tests the fallback to default.
@@ -183,11 +157,9 @@ func TestFallbackDefault(t *testing.T) {
err := mux.Register("testing", "index", NewTestHandler("default", assert))
assert.Nil(err)
// Perform test requests.
- resp := ts.DoRequest(&restaudit.Request{
- Method: "GET",
- Path: "/base/x/y",
- })
- assert.Substring("Resource: y", string(resp.Body))
+ req := restaudit.NewRequest("GET", "/base/x/y")
+ resp := ts.DoRequest(req)
+ resp.AssertContentMatch(assert, `.*Resource: y.*`)
}
// TestHandlerStack tests a complete handler stack.
@@ -204,25 +176,17 @@ func TestHandlerStack(t *testing.T) {
})
assert.Nil(err)
// Perform test requests.
- resp := ts.DoRequest(&restaudit.Request{
- Method: "GET",
- Path: "/base/test/stack",
- })
- token := resp.Header["Token"]
+ req := restaudit.NewRequest("GET", "/base/test/stack")
+ resp := ts.DoRequest(req)
+ resp.AssertContentMatch(assert, ".*Resource: token.*")
+ token := resp.AssertHeader(assert, "Token")
assert.Equal(token, "foo")
- assert.Substring("Resource: token", string(resp.Body))
- resp = ts.DoRequest(&restaudit.Request{
- Method: "GET",
- Path: "/base/test/stack",
- Header: restaudit.KeyValues{"token": "foo"},
- })
- assert.Substring("Resource: stack", string(resp.Body))
- resp = ts.DoRequest(&restaudit.Request{
- Method: "GET",
- Path: "/base/test/stack",
- Header: restaudit.KeyValues{"token": "foo"},
- })
- assert.Substring("Resource: stack", string(resp.Body))
+ req = restaudit.NewRequest("GET", "/base/test/stack")
+ req.AddHeader("token", "foo")
+ resp = ts.DoRequest(req)
+ resp.AssertContentMatch(assert, ".*Resource: stack.*")
+ resp = ts.DoRequest(req)
+ resp.AssertContentMatch(assert, ".*Resource: stack.*")
}
// TestVersion tests request and response version.
@@ -235,34 +199,27 @@ func TestVersion(t *testing.T) {
err := mux.Register("test", "json", NewTestHandler("json", assert))
assert.Nil(err)
// Perform test requests.
- resp := ts.DoRequest(&restaudit.Request{
- Method: "GET",
- Path: "/base/test/json/4711?foo=0815",
- Header: restaudit.KeyValues{
- "Accept": "application/json",
- },
- })
- vsn := resp.Header["Version"]
+ req := restaudit.NewRequest("GET", "/base/test/json/4711?foo=0815")
+ req.AddHeader(restaudit.HeaderAccept, restaudit.ApplicationJSON)
+ resp := ts.DoRequest(req)
+ resp.AssertStatus(assert, 200)
+ vsn := resp.AssertHeader(assert, "Version")
assert.Equal(vsn, "1.0.0")
- resp = ts.DoRequest(&restaudit.Request{
- Method: "GET",
- Path: "/base/test/json/4711?foo=0815",
- Header: restaudit.KeyValues{
- "Accept": "application/json",
- "Version": "2",
- },
- })
- vsn = resp.Header["Version"]
+
+ req = restaudit.NewRequest("GET", "/base/test/json/4711?foo=0815")
+ req.AddHeader(restaudit.HeaderAccept, restaudit.ApplicationJSON)
+ req.AddHeader("Version", "2")
+ resp = ts.DoRequest(req)
+ resp.AssertStatus(assert, 200)
+ vsn = resp.AssertHeader(assert, "Version")
assert.Equal(vsn, "2.0.0")
- resp = ts.DoRequest(&restaudit.Request{
- Method: "GET",
- Path: "/base/test/json/4711?foo=0815",
- Header: restaudit.KeyValues{
- "Accept": "application/json",
- "Version": "3.0",
- },
- })
- vsn = resp.Header["Version"]
+
+ req = restaudit.NewRequest("GET", "/base/test/json/4711?foo=0815")
+ req.AddHeader(restaudit.HeaderAccept, restaudit.ApplicationJSON)
+ req.AddHeader("Version", "3.0")
+ resp = ts.DoRequest(req)
+ resp.AssertStatus(assert, 200)
+ vsn = resp.AssertHeader(assert, "Version")
assert.Equal(vsn, "4.0.0-alpha")
}
@@ -318,11 +275,9 @@ func TestMethodNotSupported(t *testing.T) {
err := mux.Register("test", "method", NewTestHandler("method", assert))
assert.Nil(err)
// Perform test requests.
- resp := ts.DoRequest(&restaudit.Request{
- Method: "OPTION",
- Path: "/base/test/method",
- })
- assert.Substring("OPTION", string(resp.Body))
+ req := restaudit.NewRequest("OPTION", "/base/test/method")
+ resp := ts.DoRequest(req)
+ resp.AssertContentMatch(assert, ".*OPTION.*")
}
//--------------------
diff --git a/restaudit/doc.go b/restaudit/doc.go
index 69140b1..7f24a15 100644
--- a/restaudit/doc.go
+++ b/restaudit/doc.go
@@ -1,13 +1,15 @@
// Tideland Go REST Server Library - REST Audit
//
-// Copyright (C) 2009-2016 Frank Mueller / Tideland / Oldenburg / Germany
+// Copyright (C) 2009-2017 Frank Mueller / Tideland / Oldenburg / Germany
//
// All rights reserved. Use of this source code is governed
// by the new BSD license.
-// The Tideland Go REST Server Library restaudit package is a little
+// Package restaudit of the Tideland Go REST Server Library is a little
// helper package for the unit testing of the rest package and the
-// resource handlers.
+// resource handlers. Requests can easily be created, marshalling data
+// based on the content-type is done automatically. Response also
+// provides assert methods for the tests.
package restaudit
// EOF
diff --git a/restaudit/restaudit.go b/restaudit/restaudit.go
index 3d19e8f..6adc8a3 100644
--- a/restaudit/restaudit.go
+++ b/restaudit/restaudit.go
@@ -1,6 +1,6 @@
// Tideland Go REST Server Library - REST Audit
//
-// Copyright (C) 2009-2016 Frank Mueller / Tideland / Oldenburg / Germany
+// Copyright (C) 2009-2017 Frank Mueller / Tideland / Oldenburg / Germany
//
// All rights reserved. Use of this source code is governed
// by the new BSD license.
@@ -13,23 +13,45 @@ package restaudit
import (
"bytes"
+ "encoding/gob"
+ "encoding/json"
+ "encoding/xml"
+ "html/template"
"io"
"io/ioutil"
"mime/multipart"
"net/http"
"net/http/httptest"
+ "regexp"
"strings"
"github.com/tideland/golib/audit"
)
//--------------------
-// TEST TOOLS
+// CONSTENTS
+//--------------------
+
+const (
+ HeaderAccept = "Accept"
+ HeaderContentType = "Content-Type"
+
+ ApplicationGOB = "application/vnd.tideland.gob"
+ ApplicationJSON = "application/json"
+ ApplicationXML = "application/xml"
+)
+
+//--------------------
+// TEST TYPES
//--------------------
// KeyValues handles keys and values for request headers and cookies.
type KeyValues map[string]string
+//--------------------
+// REQUEST
+//--------------------
+
// Request wraps all infos for a test request.
type Request struct {
Method string
@@ -40,6 +62,91 @@ type Request struct {
RequestProcessor func(req *http.Request) *http.Request
}
+// NewRequest creates a new test request with the given method
+// and path.
+func NewRequest(method, path string) *Request {
+ return &Request{
+ Method: method,
+ Path: path,
+ }
+}
+
+// AddHeader adds or overwrites a request header.
+func (r *Request) AddHeader(key, value string) *Request {
+ if r.Header == nil {
+ r.Header = KeyValues{}
+ }
+ r.Header[key] = value
+ return r
+}
+
+// AddCookie adds or overwrites a request header.
+func (r *Request) AddCookie(key, value string) *Request {
+ if r.Cookies == nil {
+ r.Cookies = KeyValues{}
+ }
+ r.Cookies[key] = value
+ return r
+}
+
+// SetContent sets the request content based on the type and
+// the marshalled data.
+func (r *Request) SetContent(
+ assert audit.Assertion,
+ contentType string,
+ data interface{},
+) *Request {
+ switch contentType {
+ case ApplicationGOB:
+ body := &bytes.Buffer{}
+ enc := gob.NewEncoder(body)
+ err := enc.Encode(data)
+ assert.Nil(err, "cannot encode data to GOB")
+ r.Body = body.Bytes()
+ r.AddHeader(HeaderContentType, ApplicationGOB)
+ r.AddHeader(HeaderAccept, ApplicationGOB)
+ case ApplicationJSON:
+ body, err := json.Marshal(data)
+ assert.Nil(err, "cannot marshal data to JSON")
+ r.Body = body
+ r.AddHeader(HeaderContentType, ApplicationJSON)
+ r.AddHeader(HeaderAccept, ApplicationJSON)
+ case ApplicationXML:
+ body, err := xml.Marshal(data)
+ assert.Nil(err, "cannot marshal data to XML")
+ r.Body = body
+ r.AddHeader(HeaderContentType, ApplicationXML)
+ r.AddHeader(HeaderAccept, ApplicationXML)
+ }
+ return r
+}
+
+// RenderTemplate renders the passed data into the template
+// and assigns it to the request body. The content type
+// will be set too.
+func (r *Request) RenderTemplate(
+ assert audit.Assertion,
+ contentType string,
+ templateSource string,
+ data interface{},
+) *Request {
+ // Render template.
+ t, err := template.New(r.Path).Parse(templateSource)
+ assert.Nil(err, "cannot parse template")
+ body := &bytes.Buffer{}
+ err = t.Execute(body, data)
+ assert.Nil(err, "cannot render template")
+ r.Body = body.Bytes()
+ // Set content type.
+ r.AddHeader(HeaderContentType, contentType)
+ r.AddHeader(HeaderAccept, contentType)
+ return r
+}
+
+//--------------------
+// RESPONSE
+//--------------------
+
// Response wraps all infos of a test response.
type Response struct {
Status int
@@ -48,10 +155,62 @@ type Response struct {
Body []byte
}
+// AssertStatus checks if the status is the expected one.
+func (r *Response) AssertStatus(assert audit.Assertion, status int) {
+ assert.Equal(r.Status, status, "response status differs")
+}
+
+// AssertHeader checks if a header exists and retrieves it.
+func (r *Response) AssertHeader(assert audit.Assertion, key string) string {
+ assert.NotEmpty(r.Header, "response contains no header")
+ value, ok := r.Header[key]
+ assert.True(ok, "header '"+key+"' not found")
+ return value
+}
+
+// AssertCookie checks if a cookie exists and retrieves it.
+func (r *Response) AssertCookie(assert audit.Assertion, key string) string {
+ assert.NotEmpty(r.Cookies, "response contains no cookies")
+ value, ok := r.Cookies[key]
+ assert.True(ok, "cookie '"+key+"' not found")
+ return value
+}
+
+// AssertContent retrieves the content based on the content type
+// and unmarshals it accordingly.
+func (r *Response) AssertContent(assert audit.Assertion, data interface{}) {
+ contentType, ok := r.Header[HeaderContentType]
+ assert.True(ok)
+ switch contentType {
+ case ApplicationGOB:
+ body := bytes.NewBuffer(r.Body)
+ dec := gob.NewDecoder(body)
+ err := dec.Decode(data)
+ assert.Nil(err, "cannot decode GOB body")
+ case ApplicationJSON:
+ err := json.Unmarshal(r.Body, data)
+ assert.Nil(err, "cannot unmarshal JSON body")
+ case ApplicationXML:
+ err := xml.Unmarshal(r.Body, data)
+ assert.Nil(err, "cannot unmarshal XML body")
+ default:
+ assert.Fail("unknown content type: " + contentType)
+ }
+}
+
+// AssertContentMatch checks if the content matches a regular expression.
+func (r *Response) AssertContentMatch(assert audit.Assertion, pattern string) {
+ ok, err := regexp.MatchString(pattern, string(r.Body))
+ assert.Nil(err, "illegal content match pattern")
+ assert.True(ok, "body doesn't match pattern")
+}
+
//--------------------
// TEST SERVER
//--------------------
+// TestServer defines the test server with methods for requests
+// and uploads.
type TestServer interface {
// Close shuts down the server and blocks until all outstanding
// requests have completed.
@@ -78,12 +237,12 @@ func StartServer(handler http.Handler, assert audit.Assertion) TestServer {
}
}
-// Close is specified on the TestServer interface.
+// Close implements the TestServer interface.
func (ts *testServer) Close() {
ts.server.Close()
}
-// DoRequest is specified on the TestServer interface.
+// DoRequest implements the TestServer interface.
func (ts *testServer) DoRequest(req *Request) *Response {
// First prepare it.
transport := &http.Transport{}
@@ -115,7 +274,7 @@ func (ts *testServer) DoRequest(req *Request) *Response {
return ts.response(resp)
}
-// DoUpload is specified on the TestServer interface.
+// DoUpload implements the TestServer interface.
func (ts *testServer) DoUpload(path, fieldname, filename, data string) *Response {
// Prepare request.
transport := &http.Transport{}