mirror of
https://github.com/minio/minio.git
synced 2024-12-23 21:55:53 -05:00
Migrate to govendor to avoid limitations of godep
- over the course of a project history every maintainer needs to update its dependency packages, the problem essentially with godep is manipulating GOPATH - this manipulation leads to static objects created at different locations which end up conflicting with the overall functionality of golang. This also leads to broken builds. There is no easier way out of this other than asking developers to do 'godep restore' all the time. Which perhaps as a practice doesn't sound like a clean solution. On the other hand 'godep restore' has its own set of problems. - govendor is a right tool but a stop gap tool until we wait for golangs official 1.5 version which fixes this vendoring issue once and for all. - govendor provides consistency in terms of how import paths should be handled unlike manipulation GOPATH. This has advantages - no more compiled objects being referenced in GOPATH and build time GOPATH manging which leads to conflicts. - proper import paths referencing the exact package a project is dependent on. govendor is simple and provides the minimal necessary tooling to achieve this. For now this is the right solution.
This commit is contained in:
parent
b4c8b4877e
commit
61175ef091
@ -18,8 +18,7 @@ $ make
|
||||
Checking if proper environment variables are set.. Done
|
||||
...
|
||||
Checking dependencies for Minio.. Done
|
||||
Installed godep
|
||||
Installed cover
|
||||
Installed govet
|
||||
Building Libraries
|
||||
...
|
||||
...
|
||||
@ -37,8 +36,7 @@ $ make
|
||||
Checking if proper environment variables are set.. Done
|
||||
...
|
||||
Checking dependencies for Minio.. Done
|
||||
Installed godep
|
||||
Installed cover
|
||||
Installed govet
|
||||
Building Libraries
|
||||
...
|
||||
```
|
||||
@ -52,20 +50,17 @@ Building Libraries
|
||||
- Push to the branch (git push origin my-new-feature)
|
||||
- Create new Pull Request
|
||||
|
||||
* If you have additional dependencies for ``Minio``, ``Minio`` manages its depedencies using [godep](https://github.com/tools/godep)
|
||||
* If you have additional dependencies for ``Minio``, ``Minio`` manages its depedencies using [govendor](https://github.com/kardianos/govendor)
|
||||
- Run `go get foo/bar`
|
||||
- Edit your code to import foo/bar
|
||||
- Run `make save` from top-level directory (or `godep restore && godep save ./...`).
|
||||
- Run `govendor add foo/bar` from top-level directory
|
||||
|
||||
* When you're ready to create a pull request, be sure to:
|
||||
- Have test cases for the new code. If you have questions about how to do it, please ask in your pull request.
|
||||
- Run `go fmt
|
||||
- Run `golint`
|
||||
```
|
||||
$ go get github.com/golang/lint/golint
|
||||
$ golint ./...
|
||||
```
|
||||
- Run `make verifiers`
|
||||
- Squash your commits into a single commit. `git rebase -i`. It's okay to force update your pull request.
|
||||
- Make sure `go test -race ./...` and `go build` completes.
|
||||
|
||||
* Read [Effective Go](https://github.com/golang/go/wiki/CodeReviewComments) article from Golang project
|
||||
- `Minio` project is strictly conformant with Golang style
|
||||
- `Minio` project is fully conformant with Golang style
|
||||
- if you happen to observe offending code, please feel free to send a pull request
|
||||
|
50
Godeps/Godeps.json
generated
50
Godeps/Godeps.json
generated
@ -1,50 +0,0 @@
|
||||
{
|
||||
"ImportPath": "github.com/minio/minio",
|
||||
"GoVersion": "go1.4.2",
|
||||
"Packages": [
|
||||
"./..."
|
||||
],
|
||||
"Deps": [
|
||||
{
|
||||
"ImportPath": "github.com/dustin/go-humanize",
|
||||
"Rev": "8cc1aaa2d955ee82833337cfb10babc42be6bce6"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/facebookgo/clock",
|
||||
"Rev": "600d898af40aa09a7a93ecb9265d87b0504b6f03"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/facebookgo/httpdown",
|
||||
"Rev": "3d94c3159d8ba15fa8e9499134ccc0d8acf6adb7"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/facebookgo/stats",
|
||||
"Rev": "31fb71caf5a4f04c9f8bb3fa8e7c2597ba6eb50a"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/fatih/structs",
|
||||
"Rev": "c00d27128bb88e9c1adab1a53cda9c72c6d1ff9b"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/gorilla/context",
|
||||
"Rev": "50c25fb3b2b3b3cc724e9b6ac75fb44b3bccd0da"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/gorilla/mux",
|
||||
"Rev": "e444e69cbd2e2e3e0749a2f3c717cec491552bbf"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/gorilla/rpc/v2",
|
||||
"Rev": "f6dbf92d77c723632269bf29154cc91f2507693b"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/minio/cli",
|
||||
"Comment": "1.2.0-114-g9280cba",
|
||||
"Rev": "9280cbaadcdd26d50b5ae85123682e37944701de"
|
||||
},
|
||||
{
|
||||
"ImportPath": "gopkg.in/check.v1",
|
||||
"Rev": "64131543e7896d5bcc6bd5a76287eb75ea96c673"
|
||||
}
|
||||
]
|
||||
}
|
5
Godeps/Readme
generated
5
Godeps/Readme
generated
@ -1,5 +0,0 @@
|
||||
This directory tree is generated automatically by godep.
|
||||
|
||||
Please do not edit.
|
||||
|
||||
See https://github.com/tools/godep for more information.
|
2
Godeps/_workspace/.gitignore
generated
vendored
2
Godeps/_workspace/.gitignore
generated
vendored
@ -1,2 +0,0 @@
|
||||
/pkg
|
||||
/bin
|
6
Godeps/_workspace/src/github.com/dustin/go-humanize/.gitignore
generated
vendored
6
Godeps/_workspace/src/github.com/dustin/go-humanize/.gitignore
generated
vendored
@ -1,6 +0,0 @@
|
||||
#*
|
||||
*.[568]
|
||||
*.a
|
||||
*~
|
||||
[568].out
|
||||
_*
|
219
Godeps/_workspace/src/github.com/dustin/go-humanize/bigbytes_test.go
generated
vendored
219
Godeps/_workspace/src/github.com/dustin/go-humanize/bigbytes_test.go
generated
vendored
@ -1,219 +0,0 @@
|
||||
package humanize
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestBigByteParsing(t *testing.T) {
|
||||
tests := []struct {
|
||||
in string
|
||||
exp uint64
|
||||
}{
|
||||
{"42", 42},
|
||||
{"42MB", 42000000},
|
||||
{"42MiB", 44040192},
|
||||
{"42mb", 42000000},
|
||||
{"42mib", 44040192},
|
||||
{"42MIB", 44040192},
|
||||
{"42 MB", 42000000},
|
||||
{"42 MiB", 44040192},
|
||||
{"42 mb", 42000000},
|
||||
{"42 mib", 44040192},
|
||||
{"42 MIB", 44040192},
|
||||
{"42.5MB", 42500000},
|
||||
{"42.5MiB", 44564480},
|
||||
{"42.5 MB", 42500000},
|
||||
{"42.5 MiB", 44564480},
|
||||
// No need to say B
|
||||
{"42M", 42000000},
|
||||
{"42Mi", 44040192},
|
||||
{"42m", 42000000},
|
||||
{"42mi", 44040192},
|
||||
{"42MI", 44040192},
|
||||
{"42 M", 42000000},
|
||||
{"42 Mi", 44040192},
|
||||
{"42 m", 42000000},
|
||||
{"42 mi", 44040192},
|
||||
{"42 MI", 44040192},
|
||||
{"42.5M", 42500000},
|
||||
{"42.5Mi", 44564480},
|
||||
{"42.5 M", 42500000},
|
||||
{"42.5 Mi", 44564480},
|
||||
// Large testing, breaks when too much larger than
|
||||
// this.
|
||||
{"12.5 EB", uint64(12.5 * float64(EByte))},
|
||||
{"12.5 E", uint64(12.5 * float64(EByte))},
|
||||
{"12.5 EiB", uint64(12.5 * float64(EiByte))},
|
||||
}
|
||||
|
||||
for _, p := range tests {
|
||||
got, err := ParseBigBytes(p.in)
|
||||
if err != nil {
|
||||
t.Errorf("Couldn't parse %v: %v", p.in, err)
|
||||
} else {
|
||||
if got.Uint64() != p.exp {
|
||||
t.Errorf("Expected %v for %v, got %v",
|
||||
p.exp, p.in, got)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestBigByteErrors(t *testing.T) {
|
||||
got, err := ParseBigBytes("84 JB")
|
||||
if err == nil {
|
||||
t.Errorf("Expected error, got %v", got)
|
||||
}
|
||||
got, err = ParseBigBytes("")
|
||||
if err == nil {
|
||||
t.Errorf("Expected error parsing nothing")
|
||||
}
|
||||
}
|
||||
|
||||
func bbyte(in uint64) string {
|
||||
return BigBytes((&big.Int{}).SetUint64(in))
|
||||
}
|
||||
|
||||
func bibyte(in uint64) string {
|
||||
return BigIBytes((&big.Int{}).SetUint64(in))
|
||||
}
|
||||
|
||||
func TestBigBytes(t *testing.T) {
|
||||
testList{
|
||||
{"bytes(0)", bbyte(0), "0B"},
|
||||
{"bytes(1)", bbyte(1), "1B"},
|
||||
{"bytes(803)", bbyte(803), "803B"},
|
||||
{"bytes(999)", bbyte(999), "999B"},
|
||||
|
||||
{"bytes(1024)", bbyte(1024), "1.0KB"},
|
||||
{"bytes(1MB - 1)", bbyte(MByte - Byte), "1000KB"},
|
||||
|
||||
{"bytes(1MB)", bbyte(1024 * 1024), "1.0MB"},
|
||||
{"bytes(1GB - 1K)", bbyte(GByte - KByte), "1000MB"},
|
||||
|
||||
{"bytes(1GB)", bbyte(GByte), "1.0GB"},
|
||||
{"bytes(1TB - 1M)", bbyte(TByte - MByte), "1000GB"},
|
||||
|
||||
{"bytes(1TB)", bbyte(TByte), "1.0TB"},
|
||||
{"bytes(1PB - 1T)", bbyte(PByte - TByte), "999TB"},
|
||||
|
||||
{"bytes(1PB)", bbyte(PByte), "1.0PB"},
|
||||
{"bytes(1PB - 1T)", bbyte(EByte - PByte), "999PB"},
|
||||
|
||||
{"bytes(1EB)", bbyte(EByte), "1.0EB"},
|
||||
// Overflows.
|
||||
// {"bytes(1EB - 1P)", Bytes((KByte*EByte)-PByte), "1023EB"},
|
||||
|
||||
{"bytes(0)", bibyte(0), "0B"},
|
||||
{"bytes(1)", bibyte(1), "1B"},
|
||||
{"bytes(803)", bibyte(803), "803B"},
|
||||
{"bytes(1023)", bibyte(1023), "1023B"},
|
||||
|
||||
{"bytes(1024)", bibyte(1024), "1.0KiB"},
|
||||
{"bytes(1MB - 1)", bibyte(MiByte - IByte), "1024KiB"},
|
||||
|
||||
{"bytes(1MB)", bibyte(1024 * 1024), "1.0MiB"},
|
||||
{"bytes(1GB - 1K)", bibyte(GiByte - KiByte), "1024MiB"},
|
||||
|
||||
{"bytes(1GB)", bibyte(GiByte), "1.0GiB"},
|
||||
{"bytes(1TB - 1M)", bibyte(TiByte - MiByte), "1024GiB"},
|
||||
|
||||
{"bytes(1TB)", bibyte(TiByte), "1.0TiB"},
|
||||
{"bytes(1PB - 1T)", bibyte(PiByte - TiByte), "1023TiB"},
|
||||
|
||||
{"bytes(1PB)", bibyte(PiByte), "1.0PiB"},
|
||||
{"bytes(1PB - 1T)", bibyte(EiByte - PiByte), "1023PiB"},
|
||||
|
||||
{"bytes(1EiB)", bibyte(EiByte), "1.0EiB"},
|
||||
// Overflows.
|
||||
// {"bytes(1EB - 1P)", bibyte((KIByte*EIByte)-PiByte), "1023EB"},
|
||||
|
||||
{"bytes(5.5GiB)", bibyte(5.5 * GiByte), "5.5GiB"},
|
||||
|
||||
{"bytes(5.5GB)", bbyte(5.5 * GByte), "5.5GB"},
|
||||
}.validate(t)
|
||||
}
|
||||
|
||||
func TestVeryBigBytes(t *testing.T) {
|
||||
b, _ := (&big.Int{}).SetString("15347691069326346944512", 10)
|
||||
s := BigBytes(b)
|
||||
if s != "15ZB" {
|
||||
t.Errorf("Expected 15ZB, got %v", s)
|
||||
}
|
||||
s = BigIBytes(b)
|
||||
if s != "13ZiB" {
|
||||
t.Errorf("Expected 13ZiB, got %v", s)
|
||||
}
|
||||
|
||||
b, _ = (&big.Int{}).SetString("15716035654990179271180288", 10)
|
||||
s = BigBytes(b)
|
||||
if s != "16YB" {
|
||||
t.Errorf("Expected 16YB, got %v", s)
|
||||
}
|
||||
s = BigIBytes(b)
|
||||
if s != "13YiB" {
|
||||
t.Errorf("Expected 13YiB, got %v", s)
|
||||
}
|
||||
}
|
||||
|
||||
func TestVeryVeryBigBytes(t *testing.T) {
|
||||
b, _ := (&big.Int{}).SetString("16093220510709943573688614912", 10)
|
||||
s := BigBytes(b)
|
||||
if s != "16093YB" {
|
||||
t.Errorf("Expected 16093YB, got %v", s)
|
||||
}
|
||||
s = BigIBytes(b)
|
||||
if s != "13312YiB" {
|
||||
t.Errorf("Expected 13312YiB, got %v", s)
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseVeryBig(t *testing.T) {
|
||||
tests := []struct {
|
||||
in string
|
||||
out string
|
||||
}{
|
||||
{"16ZB", "16000000000000000000000"},
|
||||
{"16ZiB", "18889465931478580854784"},
|
||||
{"16.5ZB", "16500000000000000000000"},
|
||||
{"16.5ZiB", "19479761741837286506496"},
|
||||
{"16Z", "16000000000000000000000"},
|
||||
{"16Zi", "18889465931478580854784"},
|
||||
{"16.5Z", "16500000000000000000000"},
|
||||
{"16.5Zi", "19479761741837286506496"},
|
||||
|
||||
{"16YB", "16000000000000000000000000"},
|
||||
{"16YiB", "19342813113834066795298816"},
|
||||
{"16.5YB", "16500000000000000000000000"},
|
||||
{"16.5YiB", "19947276023641381382651904"},
|
||||
{"16Y", "16000000000000000000000000"},
|
||||
{"16Yi", "19342813113834066795298816"},
|
||||
{"16.5Y", "16500000000000000000000000"},
|
||||
{"16.5Yi", "19947276023641381382651904"},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
x, err := ParseBigBytes(test.in)
|
||||
if err != nil {
|
||||
t.Errorf("Error parsing %q: %v", test.in, err)
|
||||
continue
|
||||
}
|
||||
|
||||
if x.String() != test.out {
|
||||
t.Errorf("Expected %q for %q, got %v", test.out, test.in, x)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkParseBigBytes(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
ParseBigBytes("16.5Z")
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkBigBytes(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
bibyte(16.5 * GByte)
|
||||
}
|
||||
}
|
144
Godeps/_workspace/src/github.com/dustin/go-humanize/bytes_test.go
generated
vendored
144
Godeps/_workspace/src/github.com/dustin/go-humanize/bytes_test.go
generated
vendored
@ -1,144 +0,0 @@
|
||||
package humanize
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestByteParsing(t *testing.T) {
|
||||
tests := []struct {
|
||||
in string
|
||||
exp uint64
|
||||
}{
|
||||
{"42", 42},
|
||||
{"42MB", 42000000},
|
||||
{"42MiB", 44040192},
|
||||
{"42mb", 42000000},
|
||||
{"42mib", 44040192},
|
||||
{"42MIB", 44040192},
|
||||
{"42 MB", 42000000},
|
||||
{"42 MiB", 44040192},
|
||||
{"42 mb", 42000000},
|
||||
{"42 mib", 44040192},
|
||||
{"42 MIB", 44040192},
|
||||
{"42.5MB", 42500000},
|
||||
{"42.5MiB", 44564480},
|
||||
{"42.5 MB", 42500000},
|
||||
{"42.5 MiB", 44564480},
|
||||
// No need to say B
|
||||
{"42M", 42000000},
|
||||
{"42Mi", 44040192},
|
||||
{"42m", 42000000},
|
||||
{"42mi", 44040192},
|
||||
{"42MI", 44040192},
|
||||
{"42 M", 42000000},
|
||||
{"42 Mi", 44040192},
|
||||
{"42 m", 42000000},
|
||||
{"42 mi", 44040192},
|
||||
{"42 MI", 44040192},
|
||||
{"42.5M", 42500000},
|
||||
{"42.5Mi", 44564480},
|
||||
{"42.5 M", 42500000},
|
||||
{"42.5 Mi", 44564480},
|
||||
// Large testing, breaks when too much larger than
|
||||
// this.
|
||||
{"12.5 EB", uint64(12.5 * float64(EByte))},
|
||||
{"12.5 E", uint64(12.5 * float64(EByte))},
|
||||
{"12.5 EiB", uint64(12.5 * float64(EiByte))},
|
||||
}
|
||||
|
||||
for _, p := range tests {
|
||||
got, err := ParseBytes(p.in)
|
||||
if err != nil {
|
||||
t.Errorf("Couldn't parse %v: %v", p.in, err)
|
||||
}
|
||||
if got != p.exp {
|
||||
t.Errorf("Expected %v for %v, got %v",
|
||||
p.exp, p.in, got)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestByteErrors(t *testing.T) {
|
||||
got, err := ParseBytes("84 JB")
|
||||
if err == nil {
|
||||
t.Errorf("Expected error, got %v", got)
|
||||
}
|
||||
got, err = ParseBytes("")
|
||||
if err == nil {
|
||||
t.Errorf("Expected error parsing nothing")
|
||||
}
|
||||
got, err = ParseBytes("16 EiB")
|
||||
if err == nil {
|
||||
t.Errorf("Expected error, got %v", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBytes(t *testing.T) {
|
||||
testList{
|
||||
{"bytes(0)", Bytes(0), "0B"},
|
||||
{"bytes(1)", Bytes(1), "1B"},
|
||||
{"bytes(803)", Bytes(803), "803B"},
|
||||
{"bytes(999)", Bytes(999), "999B"},
|
||||
|
||||
{"bytes(1024)", Bytes(1024), "1.0KB"},
|
||||
{"bytes(9999)", Bytes(9999), "10KB"},
|
||||
{"bytes(1MB - 1)", Bytes(MByte - Byte), "1000KB"},
|
||||
|
||||
{"bytes(1MB)", Bytes(1024 * 1024), "1.0MB"},
|
||||
{"bytes(1GB - 1K)", Bytes(GByte - KByte), "1000MB"},
|
||||
|
||||
{"bytes(1GB)", Bytes(GByte), "1.0GB"},
|
||||
{"bytes(1TB - 1M)", Bytes(TByte - MByte), "1000GB"},
|
||||
{"bytes(10MB)", Bytes(9999 * 1000), "10MB"},
|
||||
|
||||
{"bytes(1TB)", Bytes(TByte), "1.0TB"},
|
||||
{"bytes(1PB - 1T)", Bytes(PByte - TByte), "999TB"},
|
||||
|
||||
{"bytes(1PB)", Bytes(PByte), "1.0PB"},
|
||||
{"bytes(1PB - 1T)", Bytes(EByte - PByte), "999PB"},
|
||||
|
||||
{"bytes(1EB)", Bytes(EByte), "1.0EB"},
|
||||
// Overflows.
|
||||
// {"bytes(1EB - 1P)", Bytes((KByte*EByte)-PByte), "1023EB"},
|
||||
|
||||
{"bytes(0)", IBytes(0), "0B"},
|
||||
{"bytes(1)", IBytes(1), "1B"},
|
||||
{"bytes(803)", IBytes(803), "803B"},
|
||||
{"bytes(1023)", IBytes(1023), "1023B"},
|
||||
|
||||
{"bytes(1024)", IBytes(1024), "1.0KiB"},
|
||||
{"bytes(1MB - 1)", IBytes(MiByte - IByte), "1024KiB"},
|
||||
|
||||
{"bytes(1MB)", IBytes(1024 * 1024), "1.0MiB"},
|
||||
{"bytes(1GB - 1K)", IBytes(GiByte - KiByte), "1024MiB"},
|
||||
|
||||
{"bytes(1GB)", IBytes(GiByte), "1.0GiB"},
|
||||
{"bytes(1TB - 1M)", IBytes(TiByte - MiByte), "1024GiB"},
|
||||
|
||||
{"bytes(1TB)", IBytes(TiByte), "1.0TiB"},
|
||||
{"bytes(1PB - 1T)", IBytes(PiByte - TiByte), "1023TiB"},
|
||||
|
||||
{"bytes(1PB)", IBytes(PiByte), "1.0PiB"},
|
||||
{"bytes(1PB - 1T)", IBytes(EiByte - PiByte), "1023PiB"},
|
||||
|
||||
{"bytes(1EiB)", IBytes(EiByte), "1.0EiB"},
|
||||
// Overflows.
|
||||
// {"bytes(1EB - 1P)", IBytes((KIByte*EIByte)-PiByte), "1023EB"},
|
||||
|
||||
{"bytes(5.5GiB)", IBytes(5.5 * GiByte), "5.5GiB"},
|
||||
|
||||
{"bytes(5.5GB)", Bytes(5.5 * GByte), "5.5GB"},
|
||||
}.validate(t)
|
||||
}
|
||||
|
||||
func BenchmarkParseBytes(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
ParseBytes("16.5GB")
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkBytes(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Bytes(16.5 * GByte)
|
||||
}
|
||||
}
|
134
Godeps/_workspace/src/github.com/dustin/go-humanize/comma_test.go
generated
vendored
134
Godeps/_workspace/src/github.com/dustin/go-humanize/comma_test.go
generated
vendored
@ -1,134 +0,0 @@
|
||||
package humanize
|
||||
|
||||
import (
|
||||
"math"
|
||||
"math/big"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestCommas(t *testing.T) {
|
||||
testList{
|
||||
{"0", Comma(0), "0"},
|
||||
{"10", Comma(10), "10"},
|
||||
{"100", Comma(100), "100"},
|
||||
{"1,000", Comma(1000), "1,000"},
|
||||
{"10,000", Comma(10000), "10,000"},
|
||||
{"100,000", Comma(100000), "100,000"},
|
||||
{"10,000,000", Comma(10000000), "10,000,000"},
|
||||
{"10,100,000", Comma(10100000), "10,100,000"},
|
||||
{"10,010,000", Comma(10010000), "10,010,000"},
|
||||
{"10,001,000", Comma(10001000), "10,001,000"},
|
||||
{"123,456,789", Comma(123456789), "123,456,789"},
|
||||
{"maxint", Comma(9.223372e+18), "9,223,372,000,000,000,000"},
|
||||
{"minint", Comma(-9.223372e+18), "-9,223,372,000,000,000,000"},
|
||||
{"-123,456,789", Comma(-123456789), "-123,456,789"},
|
||||
{"-10,100,000", Comma(-10100000), "-10,100,000"},
|
||||
{"-10,010,000", Comma(-10010000), "-10,010,000"},
|
||||
{"-10,001,000", Comma(-10001000), "-10,001,000"},
|
||||
{"-10,000,000", Comma(-10000000), "-10,000,000"},
|
||||
{"-100,000", Comma(-100000), "-100,000"},
|
||||
{"-10,000", Comma(-10000), "-10,000"},
|
||||
{"-1,000", Comma(-1000), "-1,000"},
|
||||
{"-100", Comma(-100), "-100"},
|
||||
{"-10", Comma(-10), "-10"},
|
||||
}.validate(t)
|
||||
}
|
||||
|
||||
func TestCommafs(t *testing.T) {
|
||||
testList{
|
||||
{"0", Commaf(0), "0"},
|
||||
{"10.11", Commaf(10.11), "10.11"},
|
||||
{"100", Commaf(100), "100"},
|
||||
{"1,000", Commaf(1000), "1,000"},
|
||||
{"10,000", Commaf(10000), "10,000"},
|
||||
{"100,000", Commaf(100000), "100,000"},
|
||||
{"834,142.32", Commaf(834142.32), "834,142.32"},
|
||||
{"10,000,000", Commaf(10000000), "10,000,000"},
|
||||
{"10,100,000", Commaf(10100000), "10,100,000"},
|
||||
{"10,010,000", Commaf(10010000), "10,010,000"},
|
||||
{"10,001,000", Commaf(10001000), "10,001,000"},
|
||||
{"123,456,789", Commaf(123456789), "123,456,789"},
|
||||
{"maxf64", Commaf(math.MaxFloat64), "179,769,313,486,231,570,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000"},
|
||||
{"minf64", Commaf(math.SmallestNonzeroFloat64), "0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005"},
|
||||
{"-123,456,789", Commaf(-123456789), "-123,456,789"},
|
||||
{"-10,100,000", Commaf(-10100000), "-10,100,000"},
|
||||
{"-10,010,000", Commaf(-10010000), "-10,010,000"},
|
||||
{"-10,001,000", Commaf(-10001000), "-10,001,000"},
|
||||
{"-10,000,000", Commaf(-10000000), "-10,000,000"},
|
||||
{"-100,000", Commaf(-100000), "-100,000"},
|
||||
{"-10,000", Commaf(-10000), "-10,000"},
|
||||
{"-1,000", Commaf(-1000), "-1,000"},
|
||||
{"-100.11", Commaf(-100.11), "-100.11"},
|
||||
{"-10", Commaf(-10), "-10"},
|
||||
}.validate(t)
|
||||
}
|
||||
|
||||
func BenchmarkCommas(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Comma(1234567890)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkCommaf(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Commaf(1234567890.83584)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkBigCommas(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
BigComma(big.NewInt(1234567890))
|
||||
}
|
||||
}
|
||||
|
||||
func bigComma(i int64) string {
|
||||
return BigComma(big.NewInt(i))
|
||||
}
|
||||
|
||||
func TestBigCommas(t *testing.T) {
|
||||
testList{
|
||||
{"0", bigComma(0), "0"},
|
||||
{"10", bigComma(10), "10"},
|
||||
{"100", bigComma(100), "100"},
|
||||
{"1,000", bigComma(1000), "1,000"},
|
||||
{"10,000", bigComma(10000), "10,000"},
|
||||
{"100,000", bigComma(100000), "100,000"},
|
||||
{"10,000,000", bigComma(10000000), "10,000,000"},
|
||||
{"10,100,000", bigComma(10100000), "10,100,000"},
|
||||
{"10,010,000", bigComma(10010000), "10,010,000"},
|
||||
{"10,001,000", bigComma(10001000), "10,001,000"},
|
||||
{"123,456,789", bigComma(123456789), "123,456,789"},
|
||||
{"maxint", bigComma(9.223372e+18), "9,223,372,000,000,000,000"},
|
||||
{"minint", bigComma(-9.223372e+18), "-9,223,372,000,000,000,000"},
|
||||
{"-123,456,789", bigComma(-123456789), "-123,456,789"},
|
||||
{"-10,100,000", bigComma(-10100000), "-10,100,000"},
|
||||
{"-10,010,000", bigComma(-10010000), "-10,010,000"},
|
||||
{"-10,001,000", bigComma(-10001000), "-10,001,000"},
|
||||
{"-10,000,000", bigComma(-10000000), "-10,000,000"},
|
||||
{"-100,000", bigComma(-100000), "-100,000"},
|
||||
{"-10,000", bigComma(-10000), "-10,000"},
|
||||
{"-1,000", bigComma(-1000), "-1,000"},
|
||||
{"-100", bigComma(-100), "-100"},
|
||||
{"-10", bigComma(-10), "-10"},
|
||||
}.validate(t)
|
||||
}
|
||||
|
||||
func TestVeryBigCommas(t *testing.T) {
|
||||
tests := []struct{ in, exp string }{
|
||||
{
|
||||
"84889279597249724975972597249849757294578485",
|
||||
"84,889,279,597,249,724,975,972,597,249,849,757,294,578,485",
|
||||
},
|
||||
{
|
||||
"-84889279597249724975972597249849757294578485",
|
||||
"-84,889,279,597,249,724,975,972,597,249,849,757,294,578,485",
|
||||
},
|
||||
}
|
||||
for _, test := range tests {
|
||||
n, _ := (&big.Int{}).SetString(test.in, 10)
|
||||
got := BigComma(n)
|
||||
if test.exp != got {
|
||||
t.Errorf("Expected %q, got %q", test.exp, got)
|
||||
}
|
||||
}
|
||||
}
|
18
Godeps/_workspace/src/github.com/dustin/go-humanize/common_test.go
generated
vendored
18
Godeps/_workspace/src/github.com/dustin/go-humanize/common_test.go
generated
vendored
@ -1,18 +0,0 @@
|
||||
package humanize
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
type testList []struct {
|
||||
name, got, exp string
|
||||
}
|
||||
|
||||
func (tl testList) validate(t *testing.T) {
|
||||
for _, test := range tl {
|
||||
if test.got != test.exp {
|
||||
t.Errorf("On %v, expected '%v', but got '%v'",
|
||||
test.name, test.exp, test.got)
|
||||
}
|
||||
}
|
||||
}
|
55
Godeps/_workspace/src/github.com/dustin/go-humanize/ftoa_test.go
generated
vendored
55
Godeps/_workspace/src/github.com/dustin/go-humanize/ftoa_test.go
generated
vendored
@ -1,55 +0,0 @@
|
||||
package humanize
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestFtoa(t *testing.T) {
|
||||
testList{
|
||||
{"200", Ftoa(200), "200"},
|
||||
{"2", Ftoa(2), "2"},
|
||||
{"2.2", Ftoa(2.2), "2.2"},
|
||||
{"2.02", Ftoa(2.02), "2.02"},
|
||||
{"200.02", Ftoa(200.02), "200.02"},
|
||||
}.validate(t)
|
||||
}
|
||||
|
||||
func BenchmarkFtoaRegexTrailing(b *testing.B) {
|
||||
trailingZerosRegex := regexp.MustCompile(`\.?0+$`)
|
||||
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
trailingZerosRegex.ReplaceAllString("2.00000", "")
|
||||
trailingZerosRegex.ReplaceAllString("2.0000", "")
|
||||
trailingZerosRegex.ReplaceAllString("2.000", "")
|
||||
trailingZerosRegex.ReplaceAllString("2.00", "")
|
||||
trailingZerosRegex.ReplaceAllString("2.0", "")
|
||||
trailingZerosRegex.ReplaceAllString("2", "")
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkFtoaFunc(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
stripTrailingZeros("2.00000")
|
||||
stripTrailingZeros("2.0000")
|
||||
stripTrailingZeros("2.000")
|
||||
stripTrailingZeros("2.00")
|
||||
stripTrailingZeros("2.0")
|
||||
stripTrailingZeros("2")
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkFmtF(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
fmt.Sprintf("%f", 2.03584)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkStrconvF(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
strconv.FormatFloat(2.03584, 'f', 6, 64)
|
||||
}
|
||||
}
|
22
Godeps/_workspace/src/github.com/dustin/go-humanize/ordinals_test.go
generated
vendored
22
Godeps/_workspace/src/github.com/dustin/go-humanize/ordinals_test.go
generated
vendored
@ -1,22 +0,0 @@
|
||||
package humanize
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestOrdinals(t *testing.T) {
|
||||
testList{
|
||||
{"0", Ordinal(0), "0th"},
|
||||
{"1", Ordinal(1), "1st"},
|
||||
{"2", Ordinal(2), "2nd"},
|
||||
{"3", Ordinal(3), "3rd"},
|
||||
{"4", Ordinal(4), "4th"},
|
||||
{"10", Ordinal(10), "10th"},
|
||||
{"11", Ordinal(11), "11th"},
|
||||
{"12", Ordinal(12), "12th"},
|
||||
{"13", Ordinal(13), "13th"},
|
||||
{"101", Ordinal(101), "101st"},
|
||||
{"102", Ordinal(102), "102nd"},
|
||||
{"103", Ordinal(103), "103rd"},
|
||||
}.validate(t)
|
||||
}
|
98
Godeps/_workspace/src/github.com/dustin/go-humanize/si_test.go
generated
vendored
98
Godeps/_workspace/src/github.com/dustin/go-humanize/si_test.go
generated
vendored
@ -1,98 +0,0 @@
|
||||
package humanize
|
||||
|
||||
import (
|
||||
"math"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestSI(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
num float64
|
||||
formatted string
|
||||
}{
|
||||
{"e-24", 1e-24, "1yF"},
|
||||
{"e-21", 1e-21, "1zF"},
|
||||
{"e-18", 1e-18, "1aF"},
|
||||
{"e-15", 1e-15, "1fF"},
|
||||
{"e-12", 1e-12, "1pF"},
|
||||
{"e-12", 2.2345e-12, "2.2345pF"},
|
||||
{"e-12", 2.23e-12, "2.23pF"},
|
||||
{"e-11", 2.23e-11, "22.3pF"},
|
||||
{"e-10", 2.2e-10, "220pF"},
|
||||
{"e-9", 2.2e-9, "2.2nF"},
|
||||
{"e-8", 2.2e-8, "22nF"},
|
||||
{"e-7", 2.2e-7, "220nF"},
|
||||
{"e-6", 2.2e-6, "2.2µF"},
|
||||
{"e-6", 1e-6, "1µF"},
|
||||
{"e-5", 2.2e-5, "22µF"},
|
||||
{"e-4", 2.2e-4, "220µF"},
|
||||
{"e-3", 2.2e-3, "2.2mF"},
|
||||
{"e-2", 2.2e-2, "22mF"},
|
||||
{"e-1", 2.2e-1, "220mF"},
|
||||
{"e+0", 2.2e-0, "2.2F"},
|
||||
{"e+0", 2.2, "2.2F"},
|
||||
{"e+1", 2.2e+1, "22F"},
|
||||
{"0", 0, "0F"},
|
||||
{"e+1", 22, "22F"},
|
||||
{"e+2", 2.2e+2, "220F"},
|
||||
{"e+2", 220, "220F"},
|
||||
{"e+3", 2.2e+3, "2.2kF"},
|
||||
{"e+3", 2200, "2.2kF"},
|
||||
{"e+4", 2.2e+4, "22kF"},
|
||||
{"e+4", 22000, "22kF"},
|
||||
{"e+5", 2.2e+5, "220kF"},
|
||||
{"e+6", 2.2e+6, "2.2MF"},
|
||||
{"e+6", 1e+6, "1MF"},
|
||||
{"e+7", 2.2e+7, "22MF"},
|
||||
{"e+8", 2.2e+8, "220MF"},
|
||||
{"e+9", 2.2e+9, "2.2GF"},
|
||||
{"e+10", 2.2e+10, "22GF"},
|
||||
{"e+11", 2.2e+11, "220GF"},
|
||||
{"e+12", 2.2e+12, "2.2TF"},
|
||||
{"e+15", 2.2e+15, "2.2PF"},
|
||||
{"e+18", 2.2e+18, "2.2EF"},
|
||||
{"e+21", 2.2e+21, "2.2ZF"},
|
||||
{"e+24", 2.2e+24, "2.2YF"},
|
||||
|
||||
// special case
|
||||
{"1F", 1000 * 1000, "1MF"},
|
||||
{"1F", 1e6, "1MF"},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
got := SI(test.num, "F")
|
||||
if got != test.formatted {
|
||||
t.Errorf("On %v (%v), got %v, wanted %v",
|
||||
test.name, test.num, got, test.formatted)
|
||||
}
|
||||
|
||||
gotf, gotu, err := ParseSI(test.formatted)
|
||||
if err != nil {
|
||||
t.Errorf("Error parsing %v (%v): %v", test.name, test.formatted, err)
|
||||
continue
|
||||
}
|
||||
|
||||
if math.Abs(1-(gotf/test.num)) > 0.01 {
|
||||
t.Errorf("On %v (%v), got %v, wanted %v (±%v)",
|
||||
test.name, test.formatted, gotf, test.num,
|
||||
math.Abs(1-(gotf/test.num)))
|
||||
}
|
||||
if gotu != "F" {
|
||||
t.Errorf("On %v (%v), expected unit F, got %v",
|
||||
test.name, test.formatted, gotu)
|
||||
}
|
||||
}
|
||||
|
||||
// Parse error
|
||||
gotf, gotu, err := ParseSI("x1.21JW") // 1.21 jigga whats
|
||||
if err == nil {
|
||||
t.Errorf("Expected error on x1.21JW, got %v %v", gotf, gotu)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkParseSI(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
ParseSI("2.2346ZB")
|
||||
}
|
||||
}
|
71
Godeps/_workspace/src/github.com/dustin/go-humanize/times_test.go
generated
vendored
71
Godeps/_workspace/src/github.com/dustin/go-humanize/times_test.go
generated
vendored
@ -1,71 +0,0 @@
|
||||
package humanize
|
||||
|
||||
import (
|
||||
"math"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestPast(t *testing.T) {
|
||||
now := time.Now().Unix()
|
||||
testList{
|
||||
{"now", Time(time.Unix(now, 0)), "now"},
|
||||
{"1 second ago", Time(time.Unix(now-1, 0)), "1 second ago"},
|
||||
{"12 seconds ago", Time(time.Unix(now-12, 0)), "12 seconds ago"},
|
||||
{"30 seconds ago", Time(time.Unix(now-30, 0)), "30 seconds ago"},
|
||||
{"45 seconds ago", Time(time.Unix(now-45, 0)), "45 seconds ago"},
|
||||
{"1 minute ago", Time(time.Unix(now-63, 0)), "1 minute ago"},
|
||||
{"15 minutes ago", Time(time.Unix(now-15*Minute, 0)), "15 minutes ago"},
|
||||
{"1 hour ago", Time(time.Unix(now-63*Minute, 0)), "1 hour ago"},
|
||||
{"2 hours ago", Time(time.Unix(now-2*Hour, 0)), "2 hours ago"},
|
||||
{"21 hours ago", Time(time.Unix(now-21*Hour, 0)), "21 hours ago"},
|
||||
{"1 day ago", Time(time.Unix(now-26*Hour, 0)), "1 day ago"},
|
||||
{"2 days ago", Time(time.Unix(now-49*Hour, 0)), "2 days ago"},
|
||||
{"3 days ago", Time(time.Unix(now-3*Day, 0)), "3 days ago"},
|
||||
{"1 week ago (1)", Time(time.Unix(now-7*Day, 0)), "1 week ago"},
|
||||
{"1 week ago (2)", Time(time.Unix(now-12*Day, 0)), "1 week ago"},
|
||||
{"2 weeks ago", Time(time.Unix(now-15*Day, 0)), "2 weeks ago"},
|
||||
{"1 month ago", Time(time.Unix(now-39*Day, 0)), "1 month ago"},
|
||||
{"3 months ago", Time(time.Unix(now-99*Day, 0)), "3 months ago"},
|
||||
{"1 year ago (1)", Time(time.Unix(now-365*Day, 0)), "1 year ago"},
|
||||
{"1 year ago (1)", Time(time.Unix(now-400*Day, 0)), "1 year ago"},
|
||||
{"2 years ago (1)", Time(time.Unix(now-548*Day, 0)), "2 years ago"},
|
||||
{"2 years ago (2)", Time(time.Unix(now-725*Day, 0)), "2 years ago"},
|
||||
{"2 years ago (3)", Time(time.Unix(now-800*Day, 0)), "2 years ago"},
|
||||
{"3 years ago", Time(time.Unix(now-3*Year, 0)), "3 years ago"},
|
||||
{"long ago", Time(time.Unix(now-LongTime, 0)), "a long while ago"},
|
||||
}.validate(t)
|
||||
}
|
||||
|
||||
func TestFuture(t *testing.T) {
|
||||
now := time.Now().Unix()
|
||||
testList{
|
||||
{"now", Time(time.Unix(now, 0)), "now"},
|
||||
{"1 second from now", Time(time.Unix(now+1, 0)), "1 second from now"},
|
||||
{"12 seconds from now", Time(time.Unix(now+12, 0)), "12 seconds from now"},
|
||||
{"30 seconds from now", Time(time.Unix(now+30, 0)), "30 seconds from now"},
|
||||
{"45 seconds from now", Time(time.Unix(now+45, 0)), "45 seconds from now"},
|
||||
{"15 minutes from now", Time(time.Unix(now+15*Minute, 0)), "15 minutes from now"},
|
||||
{"2 hours from now", Time(time.Unix(now+2*Hour, 0)), "2 hours from now"},
|
||||
{"21 hours from now", Time(time.Unix(now+21*Hour, 0)), "21 hours from now"},
|
||||
{"1 day from now", Time(time.Unix(now+26*Hour, 0)), "1 day from now"},
|
||||
{"2 days from now", Time(time.Unix(now+49*Hour, 0)), "2 days from now"},
|
||||
{"3 days from now", Time(time.Unix(now+3*Day, 0)), "3 days from now"},
|
||||
{"1 week from now (1)", Time(time.Unix(now+7*Day, 0)), "1 week from now"},
|
||||
{"1 week from now (2)", Time(time.Unix(now+12*Day, 0)), "1 week from now"},
|
||||
{"2 weeks from now", Time(time.Unix(now+15*Day, 0)), "2 weeks from now"},
|
||||
{"1 month from now", Time(time.Unix(now+30*Day, 0)), "1 month from now"},
|
||||
{"1 year from now", Time(time.Unix(now+365*Day, 0)), "1 year from now"},
|
||||
{"2 years from now", Time(time.Unix(now+2*Year, 0)), "2 years from now"},
|
||||
{"a while from now", Time(time.Unix(now+LongTime, 0)), "a long while from now"},
|
||||
}.validate(t)
|
||||
}
|
||||
|
||||
func TestRange(t *testing.T) {
|
||||
start := time.Time{}
|
||||
end := time.Unix(math.MaxInt64, math.MaxInt64)
|
||||
x := RelTime(start, end, "ago", "from now")
|
||||
if x != "a long while from now" {
|
||||
t.Errorf("Expected a long while from now, got %q", x)
|
||||
}
|
||||
}
|
536
Godeps/_workspace/src/github.com/facebookgo/clock/clock_test.go
generated
vendored
536
Godeps/_workspace/src/github.com/facebookgo/clock/clock_test.go
generated
vendored
@ -1,536 +0,0 @@
|
||||
package clock_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"runtime"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/facebookgo/clock"
|
||||
)
|
||||
|
||||
// Ensure that the clock's After channel sends at the correct time.
|
||||
func TestClock_After(t *testing.T) {
|
||||
var ok bool
|
||||
go func() {
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
ok = true
|
||||
}()
|
||||
go func() {
|
||||
time.Sleep(30 * time.Millisecond)
|
||||
t.Fatal("too late")
|
||||
}()
|
||||
gosched()
|
||||
|
||||
<-clock.New().After(20 * time.Millisecond)
|
||||
if !ok {
|
||||
t.Fatal("too early")
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure that the clock's AfterFunc executes at the correct time.
|
||||
func TestClock_AfterFunc(t *testing.T) {
|
||||
var ok bool
|
||||
go func() {
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
ok = true
|
||||
}()
|
||||
go func() {
|
||||
time.Sleep(30 * time.Millisecond)
|
||||
t.Fatal("too late")
|
||||
}()
|
||||
gosched()
|
||||
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(1)
|
||||
clock.New().AfterFunc(20*time.Millisecond, func() {
|
||||
wg.Done()
|
||||
})
|
||||
wg.Wait()
|
||||
if !ok {
|
||||
t.Fatal("too early")
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure that the clock's time matches the standary library.
|
||||
func TestClock_Now(t *testing.T) {
|
||||
a := time.Now().Round(time.Second)
|
||||
b := clock.New().Now().Round(time.Second)
|
||||
if !a.Equal(b) {
|
||||
t.Errorf("not equal: %s != %s", a, b)
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure that the clock sleeps for the appropriate amount of time.
|
||||
func TestClock_Sleep(t *testing.T) {
|
||||
var ok bool
|
||||
go func() {
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
ok = true
|
||||
}()
|
||||
go func() {
|
||||
time.Sleep(30 * time.Millisecond)
|
||||
t.Fatal("too late")
|
||||
}()
|
||||
gosched()
|
||||
|
||||
clock.New().Sleep(20 * time.Millisecond)
|
||||
if !ok {
|
||||
t.Fatal("too early")
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure that the clock ticks correctly.
|
||||
func TestClock_Tick(t *testing.T) {
|
||||
var ok bool
|
||||
go func() {
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
ok = true
|
||||
}()
|
||||
go func() {
|
||||
time.Sleep(50 * time.Millisecond)
|
||||
t.Fatal("too late")
|
||||
}()
|
||||
gosched()
|
||||
|
||||
c := clock.New().Tick(20 * time.Millisecond)
|
||||
<-c
|
||||
<-c
|
||||
if !ok {
|
||||
t.Fatal("too early")
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure that the clock's ticker ticks correctly.
|
||||
func TestClock_Ticker(t *testing.T) {
|
||||
var ok bool
|
||||
go func() {
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
ok = true
|
||||
}()
|
||||
go func() {
|
||||
time.Sleep(200 * time.Millisecond)
|
||||
t.Fatal("too late")
|
||||
}()
|
||||
gosched()
|
||||
|
||||
ticker := clock.New().Ticker(50 * time.Millisecond)
|
||||
<-ticker.C
|
||||
<-ticker.C
|
||||
if !ok {
|
||||
t.Fatal("too early")
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure that the clock's ticker can stop correctly.
|
||||
func TestClock_Ticker_Stp(t *testing.T) {
|
||||
var ok bool
|
||||
go func() {
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
ok = true
|
||||
}()
|
||||
gosched()
|
||||
|
||||
ticker := clock.New().Ticker(20 * time.Millisecond)
|
||||
<-ticker.C
|
||||
ticker.Stop()
|
||||
select {
|
||||
case <-ticker.C:
|
||||
t.Fatal("unexpected send")
|
||||
case <-time.After(30 * time.Millisecond):
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure that the clock's timer waits correctly.
|
||||
func TestClock_Timer(t *testing.T) {
|
||||
var ok bool
|
||||
go func() {
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
ok = true
|
||||
}()
|
||||
go func() {
|
||||
time.Sleep(30 * time.Millisecond)
|
||||
t.Fatal("too late")
|
||||
}()
|
||||
gosched()
|
||||
|
||||
timer := clock.New().Timer(20 * time.Millisecond)
|
||||
<-timer.C
|
||||
if !ok {
|
||||
t.Fatal("too early")
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure that the clock's timer can be stopped.
|
||||
func TestClock_Timer_Stop(t *testing.T) {
|
||||
var ok bool
|
||||
go func() {
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
ok = true
|
||||
}()
|
||||
|
||||
timer := clock.New().Timer(20 * time.Millisecond)
|
||||
timer.Stop()
|
||||
select {
|
||||
case <-timer.C:
|
||||
t.Fatal("unexpected send")
|
||||
case <-time.After(30 * time.Millisecond):
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure that the mock's After channel sends at the correct time.
|
||||
func TestMock_After(t *testing.T) {
|
||||
var ok int32
|
||||
clock := clock.NewMock()
|
||||
|
||||
// Create a channel to execute after 10 mock seconds.
|
||||
ch := clock.After(10 * time.Second)
|
||||
go func(ch <-chan time.Time) {
|
||||
<-ch
|
||||
atomic.StoreInt32(&ok, 1)
|
||||
}(ch)
|
||||
|
||||
// Move clock forward to just before the time.
|
||||
clock.Add(9 * time.Second)
|
||||
if atomic.LoadInt32(&ok) == 1 {
|
||||
t.Fatal("too early")
|
||||
}
|
||||
|
||||
// Move clock forward to the after channel's time.
|
||||
clock.Add(1 * time.Second)
|
||||
if atomic.LoadInt32(&ok) == 0 {
|
||||
t.Fatal("too late")
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure that the mock's AfterFunc executes at the correct time.
|
||||
func TestMock_AfterFunc(t *testing.T) {
|
||||
var ok int32
|
||||
clock := clock.NewMock()
|
||||
|
||||
// Execute function after duration.
|
||||
clock.AfterFunc(10*time.Second, func() {
|
||||
atomic.StoreInt32(&ok, 1)
|
||||
})
|
||||
|
||||
// Move clock forward to just before the time.
|
||||
clock.Add(9 * time.Second)
|
||||
if atomic.LoadInt32(&ok) == 1 {
|
||||
t.Fatal("too early")
|
||||
}
|
||||
|
||||
// Move clock forward to the after channel's time.
|
||||
clock.Add(1 * time.Second)
|
||||
if atomic.LoadInt32(&ok) == 0 {
|
||||
t.Fatal("too late")
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure that the mock's AfterFunc doesn't execute if stopped.
|
||||
func TestMock_AfterFunc_Stop(t *testing.T) {
|
||||
// Execute function after duration.
|
||||
clock := clock.NewMock()
|
||||
timer := clock.AfterFunc(10*time.Second, func() {
|
||||
t.Fatal("unexpected function execution")
|
||||
})
|
||||
gosched()
|
||||
|
||||
// Stop timer & move clock forward.
|
||||
timer.Stop()
|
||||
clock.Add(10 * time.Second)
|
||||
gosched()
|
||||
}
|
||||
|
||||
// Ensure that the mock's current time can be changed.
|
||||
func TestMock_Now(t *testing.T) {
|
||||
clock := clock.NewMock()
|
||||
if now := clock.Now(); !now.Equal(time.Unix(0, 0)) {
|
||||
t.Fatalf("expected epoch, got: ", now)
|
||||
}
|
||||
|
||||
// Add 10 seconds and check the time.
|
||||
clock.Add(10 * time.Second)
|
||||
if now := clock.Now(); !now.Equal(time.Unix(10, 0)) {
|
||||
t.Fatalf("expected epoch, got: ", now)
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure that the mock can sleep for the correct time.
|
||||
func TestMock_Sleep(t *testing.T) {
|
||||
var ok int32
|
||||
clock := clock.NewMock()
|
||||
|
||||
// Create a channel to execute after 10 mock seconds.
|
||||
go func() {
|
||||
clock.Sleep(10 * time.Second)
|
||||
atomic.StoreInt32(&ok, 1)
|
||||
}()
|
||||
gosched()
|
||||
|
||||
// Move clock forward to just before the sleep duration.
|
||||
clock.Add(9 * time.Second)
|
||||
if atomic.LoadInt32(&ok) == 1 {
|
||||
t.Fatal("too early")
|
||||
}
|
||||
|
||||
// Move clock forward to the after the sleep duration.
|
||||
clock.Add(1 * time.Second)
|
||||
if atomic.LoadInt32(&ok) == 0 {
|
||||
t.Fatal("too late")
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure that the mock's Tick channel sends at the correct time.
|
||||
func TestMock_Tick(t *testing.T) {
|
||||
var n int32
|
||||
clock := clock.NewMock()
|
||||
|
||||
// Create a channel to increment every 10 seconds.
|
||||
go func() {
|
||||
tick := clock.Tick(10 * time.Second)
|
||||
for {
|
||||
<-tick
|
||||
atomic.AddInt32(&n, 1)
|
||||
}
|
||||
}()
|
||||
gosched()
|
||||
|
||||
// Move clock forward to just before the first tick.
|
||||
clock.Add(9 * time.Second)
|
||||
if atomic.LoadInt32(&n) != 0 {
|
||||
t.Fatalf("expected 0, got %d", n)
|
||||
}
|
||||
|
||||
// Move clock forward to the start of the first tick.
|
||||
clock.Add(1 * time.Second)
|
||||
if atomic.LoadInt32(&n) != 1 {
|
||||
t.Fatalf("expected 1, got %d", n)
|
||||
}
|
||||
|
||||
// Move clock forward over several ticks.
|
||||
clock.Add(30 * time.Second)
|
||||
if atomic.LoadInt32(&n) != 4 {
|
||||
t.Fatalf("expected 4, got %d", n)
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure that the mock's Ticker channel sends at the correct time.
|
||||
func TestMock_Ticker(t *testing.T) {
|
||||
var n int32
|
||||
clock := clock.NewMock()
|
||||
|
||||
// Create a channel to increment every microsecond.
|
||||
go func() {
|
||||
ticker := clock.Ticker(1 * time.Microsecond)
|
||||
for {
|
||||
<-ticker.C
|
||||
atomic.AddInt32(&n, 1)
|
||||
}
|
||||
}()
|
||||
gosched()
|
||||
|
||||
// Move clock forward.
|
||||
clock.Add(10 * time.Microsecond)
|
||||
if atomic.LoadInt32(&n) != 10 {
|
||||
t.Fatalf("unexpected: %d", n)
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure that the mock's Ticker channel won't block if not read from.
|
||||
func TestMock_Ticker_Overflow(t *testing.T) {
|
||||
clock := clock.NewMock()
|
||||
ticker := clock.Ticker(1 * time.Microsecond)
|
||||
clock.Add(10 * time.Microsecond)
|
||||
ticker.Stop()
|
||||
}
|
||||
|
||||
// Ensure that the mock's Ticker can be stopped.
|
||||
func TestMock_Ticker_Stop(t *testing.T) {
|
||||
var n int32
|
||||
clock := clock.NewMock()
|
||||
|
||||
// Create a channel to increment every second.
|
||||
ticker := clock.Ticker(1 * time.Second)
|
||||
go func() {
|
||||
for {
|
||||
<-ticker.C
|
||||
atomic.AddInt32(&n, 1)
|
||||
}
|
||||
}()
|
||||
gosched()
|
||||
|
||||
// Move clock forward.
|
||||
clock.Add(5 * time.Second)
|
||||
if atomic.LoadInt32(&n) != 5 {
|
||||
t.Fatalf("expected 5, got: %d", n)
|
||||
}
|
||||
|
||||
ticker.Stop()
|
||||
|
||||
// Move clock forward again.
|
||||
clock.Add(5 * time.Second)
|
||||
if atomic.LoadInt32(&n) != 5 {
|
||||
t.Fatalf("still expected 5, got: %d", n)
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure that multiple tickers can be used together.
|
||||
func TestMock_Ticker_Multi(t *testing.T) {
|
||||
var n int32
|
||||
clock := clock.NewMock()
|
||||
|
||||
go func() {
|
||||
a := clock.Ticker(1 * time.Microsecond)
|
||||
b := clock.Ticker(3 * time.Microsecond)
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-a.C:
|
||||
atomic.AddInt32(&n, 1)
|
||||
case <-b.C:
|
||||
atomic.AddInt32(&n, 100)
|
||||
}
|
||||
}
|
||||
}()
|
||||
gosched()
|
||||
|
||||
// Move clock forward.
|
||||
clock.Add(10 * time.Microsecond)
|
||||
gosched()
|
||||
if atomic.LoadInt32(&n) != 310 {
|
||||
t.Fatalf("unexpected: %d", n)
|
||||
}
|
||||
}
|
||||
|
||||
func ExampleMock_After() {
|
||||
// Create a new mock clock.
|
||||
clock := clock.NewMock()
|
||||
count := 0
|
||||
|
||||
// Create a channel to execute after 10 mock seconds.
|
||||
go func() {
|
||||
<-clock.After(10 * time.Second)
|
||||
count = 100
|
||||
}()
|
||||
runtime.Gosched()
|
||||
|
||||
// Print the starting value.
|
||||
fmt.Printf("%s: %d\n", clock.Now().UTC(), count)
|
||||
|
||||
// Move the clock forward 5 seconds and print the value again.
|
||||
clock.Add(5 * time.Second)
|
||||
fmt.Printf("%s: %d\n", clock.Now().UTC(), count)
|
||||
|
||||
// Move the clock forward 5 seconds to the tick time and check the value.
|
||||
clock.Add(5 * time.Second)
|
||||
fmt.Printf("%s: %d\n", clock.Now().UTC(), count)
|
||||
|
||||
// Output:
|
||||
// 1970-01-01 00:00:00 +0000 UTC: 0
|
||||
// 1970-01-01 00:00:05 +0000 UTC: 0
|
||||
// 1970-01-01 00:00:10 +0000 UTC: 100
|
||||
}
|
||||
|
||||
func ExampleMock_AfterFunc() {
|
||||
// Create a new mock clock.
|
||||
clock := clock.NewMock()
|
||||
count := 0
|
||||
|
||||
// Execute a function after 10 mock seconds.
|
||||
clock.AfterFunc(10*time.Second, func() {
|
||||
count = 100
|
||||
})
|
||||
runtime.Gosched()
|
||||
|
||||
// Print the starting value.
|
||||
fmt.Printf("%s: %d\n", clock.Now().UTC(), count)
|
||||
|
||||
// Move the clock forward 10 seconds and print the new value.
|
||||
clock.Add(10 * time.Second)
|
||||
fmt.Printf("%s: %d\n", clock.Now().UTC(), count)
|
||||
|
||||
// Output:
|
||||
// 1970-01-01 00:00:00 +0000 UTC: 0
|
||||
// 1970-01-01 00:00:10 +0000 UTC: 100
|
||||
}
|
||||
|
||||
func ExampleMock_Sleep() {
|
||||
// Create a new mock clock.
|
||||
clock := clock.NewMock()
|
||||
count := 0
|
||||
|
||||
// Execute a function after 10 mock seconds.
|
||||
go func() {
|
||||
clock.Sleep(10 * time.Second)
|
||||
count = 100
|
||||
}()
|
||||
runtime.Gosched()
|
||||
|
||||
// Print the starting value.
|
||||
fmt.Printf("%s: %d\n", clock.Now().UTC(), count)
|
||||
|
||||
// Move the clock forward 10 seconds and print the new value.
|
||||
clock.Add(10 * time.Second)
|
||||
fmt.Printf("%s: %d\n", clock.Now().UTC(), count)
|
||||
|
||||
// Output:
|
||||
// 1970-01-01 00:00:00 +0000 UTC: 0
|
||||
// 1970-01-01 00:00:10 +0000 UTC: 100
|
||||
}
|
||||
|
||||
func ExampleMock_Ticker() {
|
||||
// Create a new mock clock.
|
||||
clock := clock.NewMock()
|
||||
count := 0
|
||||
|
||||
// Increment count every mock second.
|
||||
go func() {
|
||||
ticker := clock.Ticker(1 * time.Second)
|
||||
for {
|
||||
<-ticker.C
|
||||
count++
|
||||
}
|
||||
}()
|
||||
runtime.Gosched()
|
||||
|
||||
// Move the clock forward 10 seconds and print the new value.
|
||||
clock.Add(10 * time.Second)
|
||||
fmt.Printf("Count is %d after 10 seconds\n", count)
|
||||
|
||||
// Move the clock forward 5 more seconds and print the new value.
|
||||
clock.Add(5 * time.Second)
|
||||
fmt.Printf("Count is %d after 15 seconds\n", count)
|
||||
|
||||
// Output:
|
||||
// Count is 10 after 10 seconds
|
||||
// Count is 15 after 15 seconds
|
||||
}
|
||||
|
||||
func ExampleMock_Timer() {
|
||||
// Create a new mock clock.
|
||||
clock := clock.NewMock()
|
||||
count := 0
|
||||
|
||||
// Increment count after a mock second.
|
||||
go func() {
|
||||
timer := clock.Timer(1 * time.Second)
|
||||
<-timer.C
|
||||
count++
|
||||
}()
|
||||
runtime.Gosched()
|
||||
|
||||
// Move the clock forward 10 seconds and print the new value.
|
||||
clock.Add(10 * time.Second)
|
||||
fmt.Printf("Count is %d after 10 seconds\n", count)
|
||||
|
||||
// Output:
|
||||
// Count is 1 after 10 seconds
|
||||
}
|
||||
|
||||
func warn(v ...interface{}) { fmt.Fprintln(os.Stderr, v...) }
|
||||
func warnf(msg string, v ...interface{}) { fmt.Fprintf(os.Stderr, msg+"\n", v...) }
|
||||
|
||||
func gosched() { time.Sleep(1 * time.Millisecond) }
|
23
Godeps/_workspace/src/github.com/facebookgo/httpdown/.travis.yml
generated
vendored
23
Godeps/_workspace/src/github.com/facebookgo/httpdown/.travis.yml
generated
vendored
@ -1,23 +0,0 @@
|
||||
language: go
|
||||
|
||||
go:
|
||||
- 1.3
|
||||
|
||||
matrix:
|
||||
fast_finish: true
|
||||
|
||||
before_install:
|
||||
- go get -v code.google.com/p/go.tools/cmd/vet
|
||||
- go get -v github.com/golang/lint/golint
|
||||
- go get -v code.google.com/p/go.tools/cmd/cover
|
||||
|
||||
install:
|
||||
- go install -race -v std
|
||||
- go get -race -t -v ./...
|
||||
- go install -race -v ./...
|
||||
|
||||
script:
|
||||
- go vet ./...
|
||||
- $HOME/gopath/bin/golint .
|
||||
- go test -cpu=2 -race -v ./...
|
||||
- go test -cpu=2 -covermode=atomic ./...
|
43
Godeps/_workspace/src/github.com/facebookgo/httpdown/httpdown_example/main.go
generated
vendored
43
Godeps/_workspace/src/github.com/facebookgo/httpdown/httpdown_example/main.go
generated
vendored
@ -1,43 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/facebookgo/httpdown"
|
||||
)
|
||||
|
||||
func handler(w http.ResponseWriter, r *http.Request) {
|
||||
duration, err := time.ParseDuration(r.FormValue("duration"))
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), 400)
|
||||
return
|
||||
}
|
||||
fmt.Fprintf(w, "going to sleep %s with pid %d\n", duration, os.Getpid())
|
||||
w.(http.Flusher).Flush()
|
||||
time.Sleep(duration)
|
||||
fmt.Fprintf(w, "slept %s with pid %d\n", duration, os.Getpid())
|
||||
}
|
||||
|
||||
func main() {
|
||||
server := &http.Server{
|
||||
Addr: "127.0.0.1:8080",
|
||||
Handler: http.HandlerFunc(handler),
|
||||
}
|
||||
hd := &httpdown.HTTP{
|
||||
StopTimeout: 10 * time.Second,
|
||||
KillTimeout: 1 * time.Second,
|
||||
}
|
||||
|
||||
flag.StringVar(&server.Addr, "addr", server.Addr, "http address")
|
||||
flag.DurationVar(&hd.StopTimeout, "stop-timeout", hd.StopTimeout, "stop timeout")
|
||||
flag.DurationVar(&hd.KillTimeout, "kill-timeout", hd.KillTimeout, "kill timeout")
|
||||
flag.Parse()
|
||||
|
||||
if err := httpdown.ListenAndServe(server, hd); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
677
Godeps/_workspace/src/github.com/facebookgo/httpdown/httpdown_test.go
generated
vendored
677
Godeps/_workspace/src/github.com/facebookgo/httpdown/httpdown_test.go
generated
vendored
@ -1,677 +0,0 @@
|
||||
package httpdown_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/tls"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"regexp"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/facebookgo/clock"
|
||||
"github.com/facebookgo/ensure"
|
||||
"github.com/facebookgo/freeport"
|
||||
"github.com/facebookgo/httpdown"
|
||||
"github.com/facebookgo/stats"
|
||||
)
|
||||
|
||||
type onCloseListener struct {
|
||||
net.Listener
|
||||
mutex sync.Mutex
|
||||
onClose chan struct{}
|
||||
}
|
||||
|
||||
func (o *onCloseListener) Close() error {
|
||||
// Listener is closed twice, once by Grace, and once by the http library, so
|
||||
// we guard against a double close of the chan.
|
||||
defer func() {
|
||||
o.mutex.Lock()
|
||||
defer o.mutex.Unlock()
|
||||
if o.onClose != nil {
|
||||
close(o.onClose)
|
||||
o.onClose = nil
|
||||
}
|
||||
}()
|
||||
return o.Listener.Close()
|
||||
}
|
||||
|
||||
func NewOnCloseListener(l net.Listener) (net.Listener, chan struct{}) {
|
||||
c := make(chan struct{})
|
||||
return &onCloseListener{Listener: l, onClose: c}, c
|
||||
}
|
||||
|
||||
type closeErrListener struct {
|
||||
net.Listener
|
||||
err error
|
||||
}
|
||||
|
||||
func (c *closeErrListener) Close() error {
|
||||
c.Listener.Close()
|
||||
return c.err
|
||||
}
|
||||
|
||||
type acceptErrListener struct {
|
||||
net.Listener
|
||||
err chan error
|
||||
}
|
||||
|
||||
func (c *acceptErrListener) Accept() (net.Conn, error) {
|
||||
return nil, <-c.err
|
||||
}
|
||||
|
||||
type closeErrConn struct {
|
||||
net.Conn
|
||||
unblockClose chan chan struct{}
|
||||
}
|
||||
|
||||
func (c *closeErrConn) Close() error {
|
||||
ch := <-c.unblockClose
|
||||
|
||||
// Close gets called multiple times, but only the first one gets this ch
|
||||
if ch != nil {
|
||||
defer close(ch)
|
||||
}
|
||||
|
||||
return c.Conn.Close()
|
||||
}
|
||||
|
||||
type closeErrConnListener struct {
|
||||
net.Listener
|
||||
unblockClose chan chan struct{}
|
||||
}
|
||||
|
||||
func (l *closeErrConnListener) Accept() (net.Conn, error) {
|
||||
c, err := l.Listener.Accept()
|
||||
if err != nil {
|
||||
return c, err
|
||||
}
|
||||
return &closeErrConn{Conn: c, unblockClose: l.unblockClose}, nil
|
||||
}
|
||||
|
||||
func TestHTTPStopWithNoRequest(t *testing.T) {
|
||||
t.Parallel()
|
||||
listener, err := net.Listen("tcp", "127.0.0.1:0")
|
||||
ensure.Nil(t, err)
|
||||
|
||||
statsDone := make(chan struct{}, 2)
|
||||
hc := &stats.HookClient{
|
||||
BumpSumHook: func(key string, val float64) {
|
||||
if key == "serve" && val == 1 {
|
||||
statsDone <- struct{}{}
|
||||
}
|
||||
if key == "stop" && val == 1 {
|
||||
statsDone <- struct{}{}
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
server := &http.Server{}
|
||||
down := &httpdown.HTTP{Stats: hc}
|
||||
s := down.Serve(server, listener)
|
||||
ensure.Nil(t, s.Stop())
|
||||
<-statsDone
|
||||
<-statsDone
|
||||
}
|
||||
|
||||
func TestHTTPStopWithFinishedRequest(t *testing.T) {
|
||||
t.Parallel()
|
||||
hello := []byte("hello")
|
||||
fin := make(chan struct{})
|
||||
okHandler := func(w http.ResponseWriter, r *http.Request) {
|
||||
defer close(fin)
|
||||
w.Write(hello)
|
||||
}
|
||||
|
||||
listener, err := net.Listen("tcp", "127.0.0.1:0")
|
||||
ensure.Nil(t, err)
|
||||
server := &http.Server{Handler: http.HandlerFunc(okHandler)}
|
||||
transport := &http.Transport{}
|
||||
client := &http.Client{Transport: transport}
|
||||
down := &httpdown.HTTP{}
|
||||
s := down.Serve(server, listener)
|
||||
res, err := client.Get(fmt.Sprintf("http://%s/", listener.Addr().String()))
|
||||
ensure.Nil(t, err)
|
||||
actualBody, err := ioutil.ReadAll(res.Body)
|
||||
ensure.Nil(t, err)
|
||||
ensure.DeepEqual(t, actualBody, hello)
|
||||
ensure.Nil(t, res.Body.Close())
|
||||
|
||||
// At this point the request is finished, and the connection should be alive
|
||||
// but idle (because we have keep alive enabled by default in our Transport).
|
||||
ensure.Nil(t, s.Stop())
|
||||
<-fin
|
||||
|
||||
ensure.Nil(t, s.Wait())
|
||||
}
|
||||
|
||||
func TestHTTPStopWithActiveRequest(t *testing.T) {
|
||||
t.Parallel()
|
||||
const count = 10000
|
||||
hello := []byte("hello")
|
||||
finOkHandler := make(chan struct{})
|
||||
okHandler := func(w http.ResponseWriter, r *http.Request) {
|
||||
defer close(finOkHandler)
|
||||
w.WriteHeader(200)
|
||||
for i := 0; i < count; i++ {
|
||||
w.Write(hello)
|
||||
}
|
||||
}
|
||||
|
||||
listener, err := net.Listen("tcp", "127.0.0.1:0")
|
||||
ensure.Nil(t, err)
|
||||
server := &http.Server{Handler: http.HandlerFunc(okHandler)}
|
||||
transport := &http.Transport{}
|
||||
client := &http.Client{Transport: transport}
|
||||
down := &httpdown.HTTP{}
|
||||
s := down.Serve(server, listener)
|
||||
res, err := client.Get(fmt.Sprintf("http://%s/", listener.Addr().String()))
|
||||
ensure.Nil(t, err)
|
||||
|
||||
finStop := make(chan struct{})
|
||||
go func() {
|
||||
defer close(finStop)
|
||||
ensure.Nil(t, s.Stop())
|
||||
}()
|
||||
|
||||
actualBody, err := ioutil.ReadAll(res.Body)
|
||||
ensure.Nil(t, err)
|
||||
ensure.DeepEqual(t, actualBody, bytes.Repeat(hello, count))
|
||||
ensure.Nil(t, res.Body.Close())
|
||||
<-finOkHandler
|
||||
<-finStop
|
||||
}
|
||||
|
||||
func TestNewRequestAfterStop(t *testing.T) {
|
||||
t.Parallel()
|
||||
const count = 10000
|
||||
hello := []byte("hello")
|
||||
finOkHandler := make(chan struct{})
|
||||
unblockOkHandler := make(chan struct{})
|
||||
okHandler := func(w http.ResponseWriter, r *http.Request) {
|
||||
defer close(finOkHandler)
|
||||
w.WriteHeader(200)
|
||||
const diff = 500
|
||||
for i := 0; i < count-diff; i++ {
|
||||
w.Write(hello)
|
||||
}
|
||||
<-unblockOkHandler
|
||||
for i := 0; i < diff; i++ {
|
||||
w.Write(hello)
|
||||
}
|
||||
}
|
||||
|
||||
listener, err := net.Listen("tcp", "127.0.0.1:0")
|
||||
listener, onClose := NewOnCloseListener(listener)
|
||||
ensure.Nil(t, err)
|
||||
server := &http.Server{Handler: http.HandlerFunc(okHandler)}
|
||||
transport := &http.Transport{}
|
||||
client := &http.Client{Transport: transport}
|
||||
down := &httpdown.HTTP{}
|
||||
s := down.Serve(server, listener)
|
||||
res, err := client.Get(fmt.Sprintf("http://%s/", listener.Addr().String()))
|
||||
ensure.Nil(t, err)
|
||||
|
||||
finStop := make(chan struct{})
|
||||
go func() {
|
||||
defer close(finStop)
|
||||
ensure.Nil(t, s.Stop())
|
||||
}()
|
||||
|
||||
// Wait until the listener is closed.
|
||||
<-onClose
|
||||
|
||||
// Now the next request should not be able to connect as the listener is
|
||||
// now closed.
|
||||
_, err = client.Get(fmt.Sprintf("http://%s/", listener.Addr().String()))
|
||||
|
||||
// We should just get "connection refused" here, but sometimes, very rarely,
|
||||
// we get a "connection reset" instead. Unclear why this happens.
|
||||
ensure.Err(t, err, regexp.MustCompile("(connection refused|connection reset by peer)$"))
|
||||
|
||||
// Unblock the handler and ensure we finish writing the rest of the body
|
||||
// successfully.
|
||||
close(unblockOkHandler)
|
||||
actualBody, err := ioutil.ReadAll(res.Body)
|
||||
ensure.Nil(t, err)
|
||||
ensure.DeepEqual(t, actualBody, bytes.Repeat(hello, count))
|
||||
ensure.Nil(t, res.Body.Close())
|
||||
<-finOkHandler
|
||||
<-finStop
|
||||
}
|
||||
|
||||
func TestHTTPListenerCloseError(t *testing.T) {
|
||||
t.Parallel()
|
||||
expectedError := errors.New("foo")
|
||||
listener, err := net.Listen("tcp", "127.0.0.1:0")
|
||||
listener = &closeErrListener{Listener: listener, err: expectedError}
|
||||
ensure.Nil(t, err)
|
||||
server := &http.Server{}
|
||||
down := &httpdown.HTTP{}
|
||||
s := down.Serve(server, listener)
|
||||
ensure.DeepEqual(t, s.Stop(), expectedError)
|
||||
}
|
||||
|
||||
func TestHTTPServeError(t *testing.T) {
|
||||
t.Parallel()
|
||||
expectedError := errors.New("foo")
|
||||
listener, err := net.Listen("tcp", "127.0.0.1:0")
|
||||
errChan := make(chan error)
|
||||
listener = &acceptErrListener{Listener: listener, err: errChan}
|
||||
ensure.Nil(t, err)
|
||||
server := &http.Server{}
|
||||
down := &httpdown.HTTP{}
|
||||
s := down.Serve(server, listener)
|
||||
errChan <- expectedError
|
||||
ensure.DeepEqual(t, s.Wait(), expectedError)
|
||||
ensure.Nil(t, s.Stop())
|
||||
}
|
||||
|
||||
func TestHTTPWithinStopTimeout(t *testing.T) {
|
||||
t.Parallel()
|
||||
hello := []byte("hello")
|
||||
finOkHandler := make(chan struct{})
|
||||
okHandler := func(w http.ResponseWriter, r *http.Request) {
|
||||
defer close(finOkHandler)
|
||||
w.WriteHeader(200)
|
||||
w.Write(hello)
|
||||
}
|
||||
|
||||
listener, err := net.Listen("tcp", "127.0.0.1:0")
|
||||
ensure.Nil(t, err)
|
||||
server := &http.Server{Handler: http.HandlerFunc(okHandler)}
|
||||
transport := &http.Transport{}
|
||||
client := &http.Client{Transport: transport}
|
||||
down := &httpdown.HTTP{StopTimeout: time.Minute}
|
||||
s := down.Serve(server, listener)
|
||||
res, err := client.Get(fmt.Sprintf("http://%s/", listener.Addr().String()))
|
||||
ensure.Nil(t, err)
|
||||
|
||||
finStop := make(chan struct{})
|
||||
go func() {
|
||||
defer close(finStop)
|
||||
ensure.Nil(t, s.Stop())
|
||||
}()
|
||||
|
||||
actualBody, err := ioutil.ReadAll(res.Body)
|
||||
ensure.Nil(t, err)
|
||||
ensure.DeepEqual(t, actualBody, hello)
|
||||
ensure.Nil(t, res.Body.Close())
|
||||
<-finOkHandler
|
||||
<-finStop
|
||||
}
|
||||
|
||||
func TestHTTPStopTimeoutMissed(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
klock := clock.NewMock()
|
||||
|
||||
const count = 10000
|
||||
hello := []byte("hello")
|
||||
finOkHandler := make(chan struct{})
|
||||
unblockOkHandler := make(chan struct{})
|
||||
okHandler := func(w http.ResponseWriter, r *http.Request) {
|
||||
defer close(finOkHandler)
|
||||
w.Header().Set("Content-Length", fmt.Sprint(len(hello)*count))
|
||||
w.WriteHeader(200)
|
||||
for i := 0; i < count/2; i++ {
|
||||
w.Write(hello)
|
||||
}
|
||||
<-unblockOkHandler
|
||||
for i := 0; i < count/2; i++ {
|
||||
w.Write(hello)
|
||||
}
|
||||
}
|
||||
|
||||
listener, err := net.Listen("tcp", "127.0.0.1:0")
|
||||
ensure.Nil(t, err)
|
||||
server := &http.Server{Handler: http.HandlerFunc(okHandler)}
|
||||
transport := &http.Transport{}
|
||||
client := &http.Client{Transport: transport}
|
||||
down := &httpdown.HTTP{
|
||||
StopTimeout: time.Minute,
|
||||
Clock: klock,
|
||||
}
|
||||
s := down.Serve(server, listener)
|
||||
res, err := client.Get(fmt.Sprintf("http://%s/", listener.Addr().String()))
|
||||
ensure.Nil(t, err)
|
||||
|
||||
finStop := make(chan struct{})
|
||||
go func() {
|
||||
defer close(finStop)
|
||||
ensure.Nil(t, s.Stop())
|
||||
}()
|
||||
|
||||
klock.Wait(clock.Calls{After: 1}) // wait for Stop to call After
|
||||
klock.Add(down.StopTimeout)
|
||||
|
||||
_, err = ioutil.ReadAll(res.Body)
|
||||
ensure.Err(t, err, regexp.MustCompile("^unexpected EOF$"))
|
||||
ensure.Nil(t, res.Body.Close())
|
||||
close(unblockOkHandler)
|
||||
<-finOkHandler
|
||||
<-finStop
|
||||
}
|
||||
|
||||
func TestHTTPKillTimeout(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
klock := clock.NewMock()
|
||||
|
||||
statsDone := make(chan struct{}, 1)
|
||||
hc := &stats.HookClient{
|
||||
BumpSumHook: func(key string, val float64) {
|
||||
if key == "kill" && val == 1 {
|
||||
statsDone <- struct{}{}
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
const count = 10000
|
||||
hello := []byte("hello")
|
||||
finOkHandler := make(chan struct{})
|
||||
unblockOkHandler := make(chan struct{})
|
||||
okHandler := func(w http.ResponseWriter, r *http.Request) {
|
||||
defer close(finOkHandler)
|
||||
w.Header().Set("Content-Length", fmt.Sprint(len(hello)*count))
|
||||
w.WriteHeader(200)
|
||||
for i := 0; i < count/2; i++ {
|
||||
w.Write(hello)
|
||||
}
|
||||
<-unblockOkHandler
|
||||
for i := 0; i < count/2; i++ {
|
||||
w.Write(hello)
|
||||
}
|
||||
}
|
||||
|
||||
listener, err := net.Listen("tcp", "127.0.0.1:0")
|
||||
ensure.Nil(t, err)
|
||||
server := &http.Server{Handler: http.HandlerFunc(okHandler)}
|
||||
transport := &http.Transport{}
|
||||
client := &http.Client{Transport: transport}
|
||||
down := &httpdown.HTTP{
|
||||
StopTimeout: time.Minute,
|
||||
KillTimeout: time.Minute,
|
||||
Stats: hc,
|
||||
Clock: klock,
|
||||
}
|
||||
s := down.Serve(server, listener)
|
||||
res, err := client.Get(fmt.Sprintf("http://%s/", listener.Addr().String()))
|
||||
ensure.Nil(t, err)
|
||||
|
||||
finStop := make(chan struct{})
|
||||
go func() {
|
||||
defer close(finStop)
|
||||
ensure.Nil(t, s.Stop())
|
||||
}()
|
||||
|
||||
klock.Wait(clock.Calls{After: 1}) // wait for Stop to call After
|
||||
klock.Add(down.StopTimeout)
|
||||
|
||||
_, err = ioutil.ReadAll(res.Body)
|
||||
ensure.Err(t, err, regexp.MustCompile("^unexpected EOF$"))
|
||||
ensure.Nil(t, res.Body.Close())
|
||||
close(unblockOkHandler)
|
||||
<-finOkHandler
|
||||
<-finStop
|
||||
<-statsDone
|
||||
}
|
||||
|
||||
func TestHTTPKillTimeoutMissed(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
klock := clock.NewMock()
|
||||
|
||||
statsDone := make(chan struct{}, 1)
|
||||
hc := &stats.HookClient{
|
||||
BumpSumHook: func(key string, val float64) {
|
||||
if key == "kill.timeout" && val == 1 {
|
||||
statsDone <- struct{}{}
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
const count = 10000
|
||||
hello := []byte("hello")
|
||||
finOkHandler := make(chan struct{})
|
||||
unblockOkHandler := make(chan struct{})
|
||||
okHandler := func(w http.ResponseWriter, r *http.Request) {
|
||||
defer close(finOkHandler)
|
||||
w.Header().Set("Content-Length", fmt.Sprint(len(hello)*count))
|
||||
w.WriteHeader(200)
|
||||
for i := 0; i < count/2; i++ {
|
||||
w.Write(hello)
|
||||
}
|
||||
<-unblockOkHandler
|
||||
for i := 0; i < count/2; i++ {
|
||||
w.Write(hello)
|
||||
}
|
||||
}
|
||||
|
||||
listener, err := net.Listen("tcp", "127.0.0.1:0")
|
||||
ensure.Nil(t, err)
|
||||
unblockConnClose := make(chan chan struct{}, 1)
|
||||
listener = &closeErrConnListener{
|
||||
Listener: listener,
|
||||
unblockClose: unblockConnClose,
|
||||
}
|
||||
|
||||
server := &http.Server{Handler: http.HandlerFunc(okHandler)}
|
||||
transport := &http.Transport{}
|
||||
client := &http.Client{Transport: transport}
|
||||
down := &httpdown.HTTP{
|
||||
StopTimeout: time.Minute,
|
||||
KillTimeout: time.Minute,
|
||||
Stats: hc,
|
||||
Clock: klock,
|
||||
}
|
||||
s := down.Serve(server, listener)
|
||||
res, err := client.Get(fmt.Sprintf("http://%s/", listener.Addr().String()))
|
||||
ensure.Nil(t, err)
|
||||
|
||||
// Start the Stop process.
|
||||
finStop := make(chan struct{})
|
||||
go func() {
|
||||
defer close(finStop)
|
||||
ensure.Nil(t, s.Stop())
|
||||
}()
|
||||
|
||||
klock.Wait(clock.Calls{After: 1}) // wait for Stop to call After
|
||||
klock.Add(down.StopTimeout) // trigger stop timeout
|
||||
klock.Wait(clock.Calls{After: 2}) // wait for Kill to call After
|
||||
klock.Add(down.KillTimeout) // trigger kill timeout
|
||||
|
||||
// We hit both the StopTimeout & the KillTimeout.
|
||||
<-finStop
|
||||
|
||||
// Then we unblock the Close, so we get an unexpected EOF since we close
|
||||
// before we finish writing the response.
|
||||
connCloseDone := make(chan struct{})
|
||||
unblockConnClose <- connCloseDone
|
||||
<-connCloseDone
|
||||
close(unblockConnClose)
|
||||
|
||||
// Then we unblock the handler which tries to write the rest of the data.
|
||||
close(unblockOkHandler)
|
||||
|
||||
_, err = ioutil.ReadAll(res.Body)
|
||||
ensure.Err(t, err, regexp.MustCompile("^unexpected EOF$"))
|
||||
ensure.Nil(t, res.Body.Close())
|
||||
<-finOkHandler
|
||||
<-statsDone
|
||||
}
|
||||
|
||||
func TestDoubleStop(t *testing.T) {
|
||||
t.Parallel()
|
||||
listener, err := net.Listen("tcp", "127.0.0.1:0")
|
||||
ensure.Nil(t, err)
|
||||
server := &http.Server{}
|
||||
down := &httpdown.HTTP{}
|
||||
s := down.Serve(server, listener)
|
||||
ensure.Nil(t, s.Stop())
|
||||
ensure.Nil(t, s.Stop())
|
||||
}
|
||||
|
||||
func TestExistingConnState(t *testing.T) {
|
||||
t.Parallel()
|
||||
hello := []byte("hello")
|
||||
fin := make(chan struct{})
|
||||
okHandler := func(w http.ResponseWriter, r *http.Request) {
|
||||
defer close(fin)
|
||||
w.Write(hello)
|
||||
}
|
||||
|
||||
var called int32
|
||||
listener, err := net.Listen("tcp", "127.0.0.1:0")
|
||||
ensure.Nil(t, err)
|
||||
server := &http.Server{
|
||||
Handler: http.HandlerFunc(okHandler),
|
||||
ConnState: func(c net.Conn, s http.ConnState) {
|
||||
atomic.AddInt32(&called, 1)
|
||||
},
|
||||
}
|
||||
transport := &http.Transport{}
|
||||
client := &http.Client{Transport: transport}
|
||||
down := &httpdown.HTTP{}
|
||||
s := down.Serve(server, listener)
|
||||
res, err := client.Get(fmt.Sprintf("http://%s/", listener.Addr().String()))
|
||||
ensure.Nil(t, err)
|
||||
actualBody, err := ioutil.ReadAll(res.Body)
|
||||
ensure.Nil(t, err)
|
||||
ensure.DeepEqual(t, actualBody, hello)
|
||||
ensure.Nil(t, res.Body.Close())
|
||||
|
||||
ensure.Nil(t, s.Stop())
|
||||
<-fin
|
||||
|
||||
ensure.True(t, atomic.LoadInt32(&called) > 0)
|
||||
}
|
||||
|
||||
func TestHTTPDefaultListenError(t *testing.T) {
|
||||
if os.Getuid() == 0 {
|
||||
t.Skip("cant run this test as root")
|
||||
}
|
||||
|
||||
statsDone := make(chan struct{}, 1)
|
||||
hc := &stats.HookClient{
|
||||
BumpSumHook: func(key string, val float64) {
|
||||
if key == "listen.error" && val == 1 {
|
||||
statsDone <- struct{}{}
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
t.Parallel()
|
||||
down := &httpdown.HTTP{Stats: hc}
|
||||
_, err := down.ListenAndServe(&http.Server{})
|
||||
ensure.Err(t, err, regexp.MustCompile("listen tcp :80: bind: permission denied"))
|
||||
<-statsDone
|
||||
}
|
||||
|
||||
func TestHTTPSDefaultListenError(t *testing.T) {
|
||||
if os.Getuid() == 0 {
|
||||
t.Skip("cant run this test as root")
|
||||
}
|
||||
t.Parallel()
|
||||
|
||||
cert, err := tls.X509KeyPair(localhostCert, localhostKey)
|
||||
if err != nil {
|
||||
t.Fatalf("error loading cert: %v", err)
|
||||
}
|
||||
|
||||
down := &httpdown.HTTP{}
|
||||
_, err = down.ListenAndServe(&http.Server{
|
||||
TLSConfig: &tls.Config{
|
||||
NextProtos: []string{"http/1.1"},
|
||||
Certificates: []tls.Certificate{cert},
|
||||
},
|
||||
})
|
||||
ensure.Err(t, err, regexp.MustCompile("listen tcp :443: bind: permission denied"))
|
||||
}
|
||||
|
||||
func TestTLS(t *testing.T) {
|
||||
t.Parallel()
|
||||
port, err := freeport.Get()
|
||||
ensure.Nil(t, err)
|
||||
|
||||
cert, err := tls.X509KeyPair(localhostCert, localhostKey)
|
||||
if err != nil {
|
||||
t.Fatalf("error loading cert: %v", err)
|
||||
}
|
||||
const count = 10000
|
||||
hello := []byte("hello")
|
||||
finOkHandler := make(chan struct{})
|
||||
okHandler := func(w http.ResponseWriter, r *http.Request) {
|
||||
defer close(finOkHandler)
|
||||
w.WriteHeader(200)
|
||||
for i := 0; i < count; i++ {
|
||||
w.Write(hello)
|
||||
}
|
||||
}
|
||||
|
||||
server := &http.Server{
|
||||
Addr: fmt.Sprintf("0.0.0.0:%d", port),
|
||||
Handler: http.HandlerFunc(okHandler),
|
||||
TLSConfig: &tls.Config{
|
||||
NextProtos: []string{"http/1.1"},
|
||||
Certificates: []tls.Certificate{cert},
|
||||
},
|
||||
}
|
||||
transport := &http.Transport{
|
||||
TLSClientConfig: &tls.Config{
|
||||
InsecureSkipVerify: true,
|
||||
},
|
||||
}
|
||||
client := &http.Client{Transport: transport}
|
||||
down := &httpdown.HTTP{}
|
||||
s, err := down.ListenAndServe(server)
|
||||
ensure.Nil(t, err)
|
||||
res, err := client.Get(fmt.Sprintf("https://%s/", server.Addr))
|
||||
ensure.Nil(t, err)
|
||||
|
||||
finStop := make(chan struct{})
|
||||
go func() {
|
||||
defer close(finStop)
|
||||
ensure.Nil(t, s.Stop())
|
||||
}()
|
||||
|
||||
actualBody, err := ioutil.ReadAll(res.Body)
|
||||
ensure.Nil(t, err)
|
||||
ensure.DeepEqual(t, actualBody, bytes.Repeat(hello, count))
|
||||
ensure.Nil(t, res.Body.Close())
|
||||
<-finOkHandler
|
||||
<-finStop
|
||||
}
|
||||
|
||||
// localhostCert is a PEM-encoded TLS cert with SAN IPs
|
||||
// "127.0.0.1" and "[::1]", expiring at the last second of 2049 (the end
|
||||
// of ASN.1 time).
|
||||
// generated from src/pkg/crypto/tls:
|
||||
// go run generate_cert.go --rsa-bits 512 --host 127.0.0.1,::1,example.com --ca --start-date "Jan 1 00:00:00 1970" --duration=1000000h
|
||||
var localhostCert = []byte(`-----BEGIN CERTIFICATE-----
|
||||
MIIBdzCCASOgAwIBAgIBADALBgkqhkiG9w0BAQUwEjEQMA4GA1UEChMHQWNtZSBD
|
||||
bzAeFw03MDAxMDEwMDAwMDBaFw00OTEyMzEyMzU5NTlaMBIxEDAOBgNVBAoTB0Fj
|
||||
bWUgQ28wWjALBgkqhkiG9w0BAQEDSwAwSAJBALyCfqwwip8BvTKgVKGdmjZTU8DD
|
||||
ndR+WALmFPIRqn89bOU3s30olKiqYEju/SFoEvMyFRT/TWEhXHDaufThqaMCAwEA
|
||||
AaNoMGYwDgYDVR0PAQH/BAQDAgCkMBMGA1UdJQQMMAoGCCsGAQUFBwMBMA8GA1Ud
|
||||
EwEB/wQFMAMBAf8wLgYDVR0RBCcwJYILZXhhbXBsZS5jb22HBH8AAAGHEAAAAAAA
|
||||
AAAAAAAAAAAAAAEwCwYJKoZIhvcNAQEFA0EAr/09uy108p51rheIOSnz4zgduyTl
|
||||
M+4AmRo8/U1twEZLgfAGG/GZjREv2y4mCEUIM3HebCAqlA5jpRg76Rf8jw==
|
||||
-----END CERTIFICATE-----`)
|
||||
|
||||
// localhostKey is the private key for localhostCert.
|
||||
var localhostKey = []byte(`-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIBOQIBAAJBALyCfqwwip8BvTKgVKGdmjZTU8DDndR+WALmFPIRqn89bOU3s30o
|
||||
lKiqYEju/SFoEvMyFRT/TWEhXHDaufThqaMCAwEAAQJAPXuWUxTV8XyAt8VhNQER
|
||||
LgzJcUKb9JVsoS1nwXgPksXnPDKnL9ax8VERrdNr+nZbj2Q9cDSXBUovfdtehcdP
|
||||
qQIhAO48ZsPylbTrmtjDEKiHT2Ik04rLotZYS2U873J6I7WlAiEAypDjYxXyafv/
|
||||
Yo1pm9onwcetQKMW8CS3AjuV9Axzj6cCIEx2Il19fEMG4zny0WPlmbrcKvD/DpJQ
|
||||
4FHrzsYlIVTpAiAas7S1uAvneqd0l02HlN9OxQKKlbUNXNme+rnOnOGS2wIgS0jW
|
||||
zl1jvrOSJeP1PpAHohWz6LOhEr8uvltWkN6x3vE=
|
||||
-----END RSA PRIVATE KEY-----`)
|
24
Godeps/_workspace/src/github.com/facebookgo/stats/.travis.yml
generated
vendored
24
Godeps/_workspace/src/github.com/facebookgo/stats/.travis.yml
generated
vendored
@ -1,24 +0,0 @@
|
||||
language: go
|
||||
|
||||
go:
|
||||
- 1.2
|
||||
- 1.3
|
||||
|
||||
matrix:
|
||||
fast_finish: true
|
||||
|
||||
before_install:
|
||||
- go get -v code.google.com/p/go.tools/cmd/vet
|
||||
- go get -v github.com/golang/lint/golint
|
||||
- go get -v code.google.com/p/go.tools/cmd/cover
|
||||
|
||||
install:
|
||||
- go install -race -v std
|
||||
- go get -race -t -v ./...
|
||||
- go install -race -v ./...
|
||||
|
||||
script:
|
||||
- go vet ./...
|
||||
- $HOME/gopath/bin/golint .
|
||||
- go test -cpu=2 -race -v ./...
|
||||
- go test -cpu=2 -covermode=atomic ./...
|
77
Godeps/_workspace/src/github.com/facebookgo/stats/stats_test.go
generated
vendored
77
Godeps/_workspace/src/github.com/facebookgo/stats/stats_test.go
generated
vendored
@ -1,77 +0,0 @@
|
||||
package stats_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/facebookgo/ensure"
|
||||
"github.com/facebookgo/stats"
|
||||
)
|
||||
|
||||
// Ensure calling End works even when a BumpTimeHook isn't provided.
|
||||
func TestHookClientBumpTime(t *testing.T) {
|
||||
(&stats.HookClient{}).BumpTime("foo").End()
|
||||
}
|
||||
|
||||
func TestPrefixClient(t *testing.T) {
|
||||
const (
|
||||
prefix1 = "prefix1"
|
||||
prefix2 = "prefix2"
|
||||
avgKey = "avg"
|
||||
avgVal = float64(1)
|
||||
sumKey = "sum"
|
||||
sumVal = float64(2)
|
||||
histogramKey = "histogram"
|
||||
histogramVal = float64(3)
|
||||
timeKey = "time"
|
||||
)
|
||||
|
||||
var keys []string
|
||||
hc := &stats.HookClient{
|
||||
BumpAvgHook: func(key string, val float64) {
|
||||
keys = append(keys, key)
|
||||
ensure.DeepEqual(t, val, avgVal)
|
||||
},
|
||||
BumpSumHook: func(key string, val float64) {
|
||||
keys = append(keys, key)
|
||||
ensure.DeepEqual(t, val, sumVal)
|
||||
},
|
||||
BumpHistogramHook: func(key string, val float64) {
|
||||
keys = append(keys, key)
|
||||
ensure.DeepEqual(t, val, histogramVal)
|
||||
},
|
||||
BumpTimeHook: func(key string) interface {
|
||||
End()
|
||||
} {
|
||||
return multiEnderTest{
|
||||
EndHook: func() {
|
||||
keys = append(keys, key)
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
pc := stats.PrefixClient([]string{prefix1, prefix2}, hc)
|
||||
pc.BumpAvg(avgKey, avgVal)
|
||||
pc.BumpSum(sumKey, sumVal)
|
||||
pc.BumpHistogram(histogramKey, histogramVal)
|
||||
pc.BumpTime(timeKey).End()
|
||||
|
||||
ensure.SameElements(t, keys, []string{
|
||||
prefix1 + avgKey,
|
||||
prefix1 + sumKey,
|
||||
prefix1 + histogramKey,
|
||||
prefix1 + timeKey,
|
||||
prefix2 + avgKey,
|
||||
prefix2 + sumKey,
|
||||
prefix2 + histogramKey,
|
||||
prefix2 + timeKey,
|
||||
})
|
||||
}
|
||||
|
||||
type multiEnderTest struct {
|
||||
EndHook func()
|
||||
}
|
||||
|
||||
func (e multiEnderTest) End() {
|
||||
e.EndHook()
|
||||
}
|
23
Godeps/_workspace/src/github.com/fatih/structs/.gitignore
generated
vendored
23
Godeps/_workspace/src/github.com/fatih/structs/.gitignore
generated
vendored
@ -1,23 +0,0 @@
|
||||
# Compiled Object files, Static and Dynamic libs (Shared Objects)
|
||||
*.o
|
||||
*.a
|
||||
*.so
|
||||
|
||||
# Folders
|
||||
_obj
|
||||
_test
|
||||
|
||||
# Architecture specific extensions/prefixes
|
||||
*.[568vq]
|
||||
[568vq].out
|
||||
|
||||
*.cgo1.go
|
||||
*.cgo2.c
|
||||
_cgo_defun.c
|
||||
_cgo_gotypes.go
|
||||
_cgo_export.*
|
||||
|
||||
_testmain.go
|
||||
|
||||
*.exe
|
||||
*.test
|
11
Godeps/_workspace/src/github.com/fatih/structs/.travis.yml
generated
vendored
11
Godeps/_workspace/src/github.com/fatih/structs/.travis.yml
generated
vendored
@ -1,11 +0,0 @@
|
||||
language: go
|
||||
go: 1.3
|
||||
before_install:
|
||||
- go get github.com/axw/gocov/gocov
|
||||
- go get github.com/mattn/goveralls
|
||||
- go get code.google.com/p/go.tools/cmd/cover
|
||||
script:
|
||||
- $HOME/gopath/bin/goveralls -repotoken $COVERALLS_TOKEN
|
||||
env:
|
||||
global:
|
||||
- secure: hkc+92KPmMFqIH9n4yWdnH1JpZjahmOyDJwpTh8Yl0JieJNG0XEXpOqNao27eA0cLF+UHdyjFeGcPUJKNmgE46AoQjtovt+ICjCXKR2yF6S2kKJcUOz/Vd6boZF7qHV06jjxyxOebpID5iSoW6UfFr001bFxpd3jaSLFTzSHWRQ=
|
324
Godeps/_workspace/src/github.com/fatih/structs/field_test.go
generated
vendored
324
Godeps/_workspace/src/github.com/fatih/structs/field_test.go
generated
vendored
@ -1,324 +0,0 @@
|
||||
package structs
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// A test struct that defines all cases
|
||||
type Foo struct {
|
||||
A string
|
||||
B int `structs:"y"`
|
||||
C bool `json:"c"`
|
||||
d string // not exported
|
||||
E *Baz
|
||||
x string `xml:"x"` // not exported, with tag
|
||||
Y []string
|
||||
Z map[string]interface{}
|
||||
*Bar // embedded
|
||||
}
|
||||
|
||||
type Baz struct {
|
||||
A string
|
||||
B int
|
||||
}
|
||||
|
||||
type Bar struct {
|
||||
E string
|
||||
F int
|
||||
g []string
|
||||
}
|
||||
|
||||
func newStruct() *Struct {
|
||||
b := &Bar{
|
||||
E: "example",
|
||||
F: 2,
|
||||
g: []string{"zeynep", "fatih"},
|
||||
}
|
||||
|
||||
// B and x is not initialized for testing
|
||||
f := &Foo{
|
||||
A: "gopher",
|
||||
C: true,
|
||||
d: "small",
|
||||
E: nil,
|
||||
Y: []string{"example"},
|
||||
Z: nil,
|
||||
}
|
||||
f.Bar = b
|
||||
|
||||
return New(f)
|
||||
}
|
||||
|
||||
func TestField_Set(t *testing.T) {
|
||||
s := newStruct()
|
||||
|
||||
f := s.Field("A")
|
||||
err := f.Set("fatih")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if f.Value().(string) != "fatih" {
|
||||
t.Errorf("Setted value is wrong: %s want: %s", f.Value().(string), "fatih")
|
||||
}
|
||||
|
||||
f = s.Field("Y")
|
||||
err = f.Set([]string{"override", "with", "this"})
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
sliceLen := len(f.Value().([]string))
|
||||
if sliceLen != 3 {
|
||||
t.Errorf("Setted values slice length is wrong: %d, want: %d", sliceLen, 3)
|
||||
}
|
||||
|
||||
f = s.Field("C")
|
||||
err = f.Set(false)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if f.Value().(bool) {
|
||||
t.Errorf("Setted value is wrong: %s want: %s", f.Value().(bool), false)
|
||||
}
|
||||
|
||||
// let's pass a different type
|
||||
f = s.Field("A")
|
||||
err = f.Set(123) // Field A is of type string, but we are going to pass an integer
|
||||
if err == nil {
|
||||
t.Error("Setting a field's value with a different type than the field's type should return an error")
|
||||
}
|
||||
|
||||
// old value should be still there :)
|
||||
if f.Value().(string) != "fatih" {
|
||||
t.Errorf("Setted value is wrong: %s want: %s", f.Value().(string), "fatih")
|
||||
}
|
||||
|
||||
// let's access an unexported field, which should give an error
|
||||
f = s.Field("d")
|
||||
err = f.Set("large")
|
||||
if err != errNotExported {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
// let's set a pointer to struct
|
||||
b := &Bar{
|
||||
E: "gopher",
|
||||
F: 2,
|
||||
}
|
||||
|
||||
f = s.Field("Bar")
|
||||
err = f.Set(b)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
baz := &Baz{
|
||||
A: "helloWorld",
|
||||
B: 42,
|
||||
}
|
||||
|
||||
f = s.Field("E")
|
||||
err = f.Set(baz)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
ba := s.Field("E").Value().(*Baz)
|
||||
|
||||
if ba.A != "helloWorld" {
|
||||
t.Errorf("could not set baz. Got: %s Want: helloWorld", ba.A)
|
||||
}
|
||||
}
|
||||
|
||||
func TestField(t *testing.T) {
|
||||
s := newStruct()
|
||||
|
||||
defer func() {
|
||||
err := recover()
|
||||
if err == nil {
|
||||
t.Error("Retrieveing a non existing field from the struct should panic")
|
||||
}
|
||||
}()
|
||||
|
||||
_ = s.Field("no-field")
|
||||
}
|
||||
|
||||
func TestField_Kind(t *testing.T) {
|
||||
s := newStruct()
|
||||
|
||||
f := s.Field("A")
|
||||
if f.Kind() != reflect.String {
|
||||
t.Errorf("Field A has wrong kind: %s want: %s", f.Kind(), reflect.String)
|
||||
}
|
||||
|
||||
f = s.Field("B")
|
||||
if f.Kind() != reflect.Int {
|
||||
t.Errorf("Field B has wrong kind: %s want: %s", f.Kind(), reflect.Int)
|
||||
}
|
||||
|
||||
// unexported
|
||||
f = s.Field("d")
|
||||
if f.Kind() != reflect.String {
|
||||
t.Errorf("Field d has wrong kind: %s want: %s", f.Kind(), reflect.String)
|
||||
}
|
||||
}
|
||||
|
||||
func TestField_Tag(t *testing.T) {
|
||||
s := newStruct()
|
||||
|
||||
v := s.Field("B").Tag("json")
|
||||
if v != "" {
|
||||
t.Errorf("Field's tag value of a non existing tag should return empty, got: %s", v)
|
||||
}
|
||||
|
||||
v = s.Field("C").Tag("json")
|
||||
if v != "c" {
|
||||
t.Errorf("Field's tag value of the existing field C should return 'c', got: %s", v)
|
||||
}
|
||||
|
||||
v = s.Field("d").Tag("json")
|
||||
if v != "" {
|
||||
t.Errorf("Field's tag value of a non exported field should return empty, got: %s", v)
|
||||
}
|
||||
|
||||
v = s.Field("x").Tag("xml")
|
||||
if v != "x" {
|
||||
t.Errorf("Field's tag value of a non exported field with a tag should return 'x', got: %s", v)
|
||||
}
|
||||
|
||||
v = s.Field("A").Tag("json")
|
||||
if v != "" {
|
||||
t.Errorf("Field's tag value of a existing field without a tag should return empty, got: %s", v)
|
||||
}
|
||||
}
|
||||
|
||||
func TestField_Value(t *testing.T) {
|
||||
s := newStruct()
|
||||
|
||||
v := s.Field("A").Value()
|
||||
val, ok := v.(string)
|
||||
if !ok {
|
||||
t.Errorf("Field's value of a A should be string")
|
||||
}
|
||||
|
||||
if val != "gopher" {
|
||||
t.Errorf("Field's value of a existing tag should return 'gopher', got: %s", val)
|
||||
}
|
||||
|
||||
defer func() {
|
||||
err := recover()
|
||||
if err == nil {
|
||||
t.Error("Value of a non exported field from the field should panic")
|
||||
}
|
||||
}()
|
||||
|
||||
// should panic
|
||||
_ = s.Field("d").Value()
|
||||
}
|
||||
|
||||
func TestField_IsEmbedded(t *testing.T) {
|
||||
s := newStruct()
|
||||
|
||||
if !s.Field("Bar").IsEmbedded() {
|
||||
t.Errorf("Fields 'Bar' field is an embedded field")
|
||||
}
|
||||
|
||||
if s.Field("d").IsEmbedded() {
|
||||
t.Errorf("Fields 'd' field is not an embedded field")
|
||||
}
|
||||
}
|
||||
|
||||
func TestField_IsExported(t *testing.T) {
|
||||
s := newStruct()
|
||||
|
||||
if !s.Field("Bar").IsExported() {
|
||||
t.Errorf("Fields 'Bar' field is an exported field")
|
||||
}
|
||||
|
||||
if !s.Field("A").IsExported() {
|
||||
t.Errorf("Fields 'A' field is an exported field")
|
||||
}
|
||||
|
||||
if s.Field("d").IsExported() {
|
||||
t.Errorf("Fields 'd' field is not an exported field")
|
||||
}
|
||||
}
|
||||
|
||||
func TestField_IsZero(t *testing.T) {
|
||||
s := newStruct()
|
||||
|
||||
if s.Field("A").IsZero() {
|
||||
t.Errorf("Fields 'A' field is an initialized field")
|
||||
}
|
||||
|
||||
if !s.Field("B").IsZero() {
|
||||
t.Errorf("Fields 'B' field is not an initialized field")
|
||||
}
|
||||
}
|
||||
|
||||
func TestField_Name(t *testing.T) {
|
||||
s := newStruct()
|
||||
|
||||
if s.Field("A").Name() != "A" {
|
||||
t.Errorf("Fields 'A' field should have the name 'A'")
|
||||
}
|
||||
}
|
||||
|
||||
func TestField_Field(t *testing.T) {
|
||||
s := newStruct()
|
||||
|
||||
e := s.Field("Bar").Field("E")
|
||||
|
||||
val, ok := e.Value().(string)
|
||||
if !ok {
|
||||
t.Error("The value of the field 'e' inside 'Bar' struct should be string")
|
||||
}
|
||||
|
||||
if val != "example" {
|
||||
t.Errorf("The value of 'e' should be 'example, got: %s", val)
|
||||
}
|
||||
|
||||
defer func() {
|
||||
err := recover()
|
||||
if err == nil {
|
||||
t.Error("Field of a non existing nested struct should panic")
|
||||
}
|
||||
}()
|
||||
|
||||
_ = s.Field("Bar").Field("e")
|
||||
}
|
||||
|
||||
func TestField_Fields(t *testing.T) {
|
||||
s := newStruct()
|
||||
fields := s.Field("Bar").Fields()
|
||||
|
||||
if len(fields) != 3 {
|
||||
t.Errorf("We expect 3 fields in embedded struct, was: %d", len(fields))
|
||||
}
|
||||
}
|
||||
|
||||
func TestField_FieldOk(t *testing.T) {
|
||||
s := newStruct()
|
||||
|
||||
b, ok := s.FieldOk("Bar")
|
||||
if !ok {
|
||||
t.Error("The field 'Bar' should exists.")
|
||||
}
|
||||
|
||||
e, ok := b.FieldOk("E")
|
||||
if !ok {
|
||||
t.Error("The field 'E' should exists.")
|
||||
}
|
||||
|
||||
val, ok := e.Value().(string)
|
||||
if !ok {
|
||||
t.Error("The value of the field 'e' inside 'Bar' struct should be string")
|
||||
}
|
||||
|
||||
if val != "example" {
|
||||
t.Errorf("The value of 'e' should be 'example, got: %s", val)
|
||||
}
|
||||
}
|
351
Godeps/_workspace/src/github.com/fatih/structs/structs_example_test.go
generated
vendored
351
Godeps/_workspace/src/github.com/fatih/structs/structs_example_test.go
generated
vendored
@ -1,351 +0,0 @@
|
||||
package structs
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
func ExampleNew() {
|
||||
type Server struct {
|
||||
Name string
|
||||
ID int32
|
||||
Enabled bool
|
||||
}
|
||||
|
||||
server := &Server{
|
||||
Name: "Arslan",
|
||||
ID: 123456,
|
||||
Enabled: true,
|
||||
}
|
||||
|
||||
s := New(server)
|
||||
|
||||
fmt.Printf("Name : %v\n", s.Name())
|
||||
fmt.Printf("Values : %v\n", s.Values())
|
||||
fmt.Printf("Value of ID : %v\n", s.Field("ID").Value())
|
||||
// Output:
|
||||
// Name : Server
|
||||
// Values : [Arslan 123456 true]
|
||||
// Value of ID : 123456
|
||||
|
||||
}
|
||||
|
||||
func ExampleMap() {
|
||||
type Server struct {
|
||||
Name string
|
||||
ID int32
|
||||
Enabled bool
|
||||
}
|
||||
|
||||
s := &Server{
|
||||
Name: "Arslan",
|
||||
ID: 123456,
|
||||
Enabled: true,
|
||||
}
|
||||
|
||||
m := Map(s)
|
||||
|
||||
fmt.Printf("%#v\n", m["Name"])
|
||||
fmt.Printf("%#v\n", m["ID"])
|
||||
fmt.Printf("%#v\n", m["Enabled"])
|
||||
// Output:
|
||||
// "Arslan"
|
||||
// 123456
|
||||
// true
|
||||
|
||||
}
|
||||
|
||||
func ExampleMap_tags() {
|
||||
// Custom tags can change the map keys instead of using the fields name
|
||||
type Server struct {
|
||||
Name string `structs:"server_name"`
|
||||
ID int32 `structs:"server_id"`
|
||||
Enabled bool `structs:"enabled"`
|
||||
}
|
||||
|
||||
s := &Server{
|
||||
Name: "Zeynep",
|
||||
ID: 789012,
|
||||
}
|
||||
|
||||
m := Map(s)
|
||||
|
||||
// access them by the custom tags defined above
|
||||
fmt.Printf("%#v\n", m["server_name"])
|
||||
fmt.Printf("%#v\n", m["server_id"])
|
||||
fmt.Printf("%#v\n", m["enabled"])
|
||||
// Output:
|
||||
// "Zeynep"
|
||||
// 789012
|
||||
// false
|
||||
|
||||
}
|
||||
|
||||
func ExampleMap_nested() {
|
||||
// By default field with struct types are processed too. We can stop
|
||||
// processing them via "omitnested" tag option.
|
||||
type Server struct {
|
||||
Name string `structs:"server_name"`
|
||||
ID int32 `structs:"server_id"`
|
||||
Time time.Time `structs:"time,omitnested"` // do not convert to map[string]interface{}
|
||||
}
|
||||
|
||||
const shortForm = "2006-Jan-02"
|
||||
t, _ := time.Parse("2006-Jan-02", "2013-Feb-03")
|
||||
|
||||
s := &Server{
|
||||
Name: "Zeynep",
|
||||
ID: 789012,
|
||||
Time: t,
|
||||
}
|
||||
|
||||
m := Map(s)
|
||||
|
||||
// access them by the custom tags defined above
|
||||
fmt.Printf("%v\n", m["server_name"])
|
||||
fmt.Printf("%v\n", m["server_id"])
|
||||
fmt.Printf("%v\n", m["time"].(time.Time))
|
||||
// Output:
|
||||
// Zeynep
|
||||
// 789012
|
||||
// 2013-02-03 00:00:00 +0000 UTC
|
||||
}
|
||||
|
||||
func ExampleMap_omitEmpty() {
|
||||
// By default field with struct types of zero values are processed too. We
|
||||
// can stop processing them via "omitempty" tag option.
|
||||
type Server struct {
|
||||
Name string `structs:",omitempty"`
|
||||
ID int32 `structs:"server_id,omitempty"`
|
||||
Location string
|
||||
}
|
||||
|
||||
// Only add location
|
||||
s := &Server{
|
||||
Location: "Tokyo",
|
||||
}
|
||||
|
||||
m := Map(s)
|
||||
|
||||
// map contains only the Location field
|
||||
fmt.Printf("%v\n", m)
|
||||
// Output:
|
||||
// map[Location:Tokyo]
|
||||
}
|
||||
|
||||
func ExampleValues() {
|
||||
type Server struct {
|
||||
Name string
|
||||
ID int32
|
||||
Enabled bool
|
||||
}
|
||||
|
||||
s := &Server{
|
||||
Name: "Fatih",
|
||||
ID: 135790,
|
||||
Enabled: false,
|
||||
}
|
||||
|
||||
m := Values(s)
|
||||
|
||||
fmt.Printf("Values: %+v\n", m)
|
||||
// Output:
|
||||
// Values: [Fatih 135790 false]
|
||||
}
|
||||
|
||||
func ExampleValues_omitEmpty() {
|
||||
// By default field with struct types of zero values are processed too. We
|
||||
// can stop processing them via "omitempty" tag option.
|
||||
type Server struct {
|
||||
Name string `structs:",omitempty"`
|
||||
ID int32 `structs:"server_id,omitempty"`
|
||||
Location string
|
||||
}
|
||||
|
||||
// Only add location
|
||||
s := &Server{
|
||||
Location: "Ankara",
|
||||
}
|
||||
|
||||
m := Values(s)
|
||||
|
||||
// values contains only the Location field
|
||||
fmt.Printf("Values: %+v\n", m)
|
||||
// Output:
|
||||
// Values: [Ankara]
|
||||
}
|
||||
|
||||
func ExampleValues_tags() {
|
||||
type Location struct {
|
||||
City string
|
||||
Country string
|
||||
}
|
||||
|
||||
type Server struct {
|
||||
Name string
|
||||
ID int32
|
||||
Enabled bool
|
||||
Location Location `structs:"-"` // values from location are not included anymore
|
||||
}
|
||||
|
||||
s := &Server{
|
||||
Name: "Fatih",
|
||||
ID: 135790,
|
||||
Enabled: false,
|
||||
Location: Location{City: "Ankara", Country: "Turkey"},
|
||||
}
|
||||
|
||||
// Let get all values from the struct s. Note that we don't include values
|
||||
// from the Location field
|
||||
m := Values(s)
|
||||
|
||||
fmt.Printf("Values: %+v\n", m)
|
||||
// Output:
|
||||
// Values: [Fatih 135790 false]
|
||||
}
|
||||
|
||||
func ExampleFields() {
|
||||
type Access struct {
|
||||
Name string
|
||||
LastAccessed time.Time
|
||||
Number int
|
||||
}
|
||||
|
||||
s := &Access{
|
||||
Name: "Fatih",
|
||||
LastAccessed: time.Now(),
|
||||
Number: 1234567,
|
||||
}
|
||||
|
||||
fields := Fields(s)
|
||||
|
||||
for i, field := range fields {
|
||||
fmt.Printf("[%d] %+v\n", i, field.Name())
|
||||
}
|
||||
|
||||
// Output:
|
||||
// [0] Name
|
||||
// [1] LastAccessed
|
||||
// [2] Number
|
||||
}
|
||||
|
||||
func ExampleFields_nested() {
|
||||
type Person struct {
|
||||
Name string
|
||||
Number int
|
||||
}
|
||||
|
||||
type Access struct {
|
||||
Person Person
|
||||
HasPermission bool
|
||||
LastAccessed time.Time
|
||||
}
|
||||
|
||||
s := &Access{
|
||||
Person: Person{Name: "fatih", Number: 1234567},
|
||||
LastAccessed: time.Now(),
|
||||
HasPermission: true,
|
||||
}
|
||||
|
||||
// Let's get all fields from the struct s.
|
||||
fields := Fields(s)
|
||||
|
||||
for _, field := range fields {
|
||||
if field.Name() == "Person" {
|
||||
fmt.Printf("Access.Person.Name: %+v\n", field.Field("Name").Value())
|
||||
}
|
||||
}
|
||||
|
||||
// Output:
|
||||
// Access.Person.Name: fatih
|
||||
}
|
||||
|
||||
func ExampleField() {
|
||||
type Person struct {
|
||||
Name string
|
||||
Number int
|
||||
}
|
||||
|
||||
type Access struct {
|
||||
Person Person
|
||||
HasPermission bool
|
||||
LastAccessed time.Time
|
||||
}
|
||||
|
||||
access := &Access{
|
||||
Person: Person{Name: "fatih", Number: 1234567},
|
||||
LastAccessed: time.Now(),
|
||||
HasPermission: true,
|
||||
}
|
||||
|
||||
// Create a new Struct type
|
||||
s := New(access)
|
||||
|
||||
// Get the Field type for "Person" field
|
||||
p := s.Field("Person")
|
||||
|
||||
// Get the underlying "Name field" and print the value of it
|
||||
name := p.Field("Name")
|
||||
|
||||
fmt.Printf("Value of Person.Access.Name: %+v\n", name.Value())
|
||||
|
||||
// Output:
|
||||
// Value of Person.Access.Name: fatih
|
||||
|
||||
}
|
||||
|
||||
func ExampleIsZero() {
|
||||
type Server struct {
|
||||
Name string
|
||||
ID int32
|
||||
Enabled bool
|
||||
}
|
||||
|
||||
// Nothing is initalized
|
||||
a := &Server{}
|
||||
isZeroA := IsZero(a)
|
||||
|
||||
// Name and Enabled is initialized, but not ID
|
||||
b := &Server{
|
||||
Name: "Golang",
|
||||
Enabled: true,
|
||||
}
|
||||
isZeroB := IsZero(b)
|
||||
|
||||
fmt.Printf("%#v\n", isZeroA)
|
||||
fmt.Printf("%#v\n", isZeroB)
|
||||
// Output:
|
||||
// true
|
||||
// false
|
||||
}
|
||||
|
||||
func ExampleHasZero() {
|
||||
// Let's define an Access struct. Note that the "Enabled" field is not
|
||||
// going to be checked because we added the "structs" tag to the field.
|
||||
type Access struct {
|
||||
Name string
|
||||
LastAccessed time.Time
|
||||
Number int
|
||||
Enabled bool `structs:"-"`
|
||||
}
|
||||
|
||||
// Name and Number is not initialized.
|
||||
a := &Access{
|
||||
LastAccessed: time.Now(),
|
||||
}
|
||||
hasZeroA := HasZero(a)
|
||||
|
||||
// Name and Number is initialized.
|
||||
b := &Access{
|
||||
Name: "Fatih",
|
||||
LastAccessed: time.Now(),
|
||||
Number: 12345,
|
||||
}
|
||||
hasZeroB := HasZero(b)
|
||||
|
||||
fmt.Printf("%#v\n", hasZeroA)
|
||||
fmt.Printf("%#v\n", hasZeroB)
|
||||
// Output:
|
||||
// true
|
||||
// false
|
||||
}
|
847
Godeps/_workspace/src/github.com/fatih/structs/structs_test.go
generated
vendored
847
Godeps/_workspace/src/github.com/fatih/structs/structs_test.go
generated
vendored
@ -1,847 +0,0 @@
|
||||
package structs
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestMapNonStruct(t *testing.T) {
|
||||
foo := []string{"foo"}
|
||||
|
||||
defer func() {
|
||||
err := recover()
|
||||
if err == nil {
|
||||
t.Error("Passing a non struct into Map should panic")
|
||||
}
|
||||
}()
|
||||
|
||||
// this should panic. We are going to recover and and test it
|
||||
_ = Map(foo)
|
||||
}
|
||||
|
||||
func TestStructIndexes(t *testing.T) {
|
||||
type C struct {
|
||||
something int
|
||||
Props map[string]interface{}
|
||||
}
|
||||
|
||||
defer func() {
|
||||
err := recover()
|
||||
if err != nil {
|
||||
fmt.Printf("err %+v\n", err)
|
||||
t.Error("Using mixed indexes should not panic")
|
||||
}
|
||||
}()
|
||||
|
||||
// They should not panic
|
||||
_ = Map(&C{})
|
||||
_ = Fields(&C{})
|
||||
_ = Values(&C{})
|
||||
_ = IsZero(&C{})
|
||||
_ = HasZero(&C{})
|
||||
}
|
||||
|
||||
func TestMap(t *testing.T) {
|
||||
var T = struct {
|
||||
A string
|
||||
B int
|
||||
C bool
|
||||
}{
|
||||
A: "a-value",
|
||||
B: 2,
|
||||
C: true,
|
||||
}
|
||||
|
||||
a := Map(T)
|
||||
|
||||
if typ := reflect.TypeOf(a).Kind(); typ != reflect.Map {
|
||||
t.Errorf("Map should return a map type, got: %v", typ)
|
||||
}
|
||||
|
||||
// we have three fields
|
||||
if len(a) != 3 {
|
||||
t.Errorf("Map should return a map of len 3, got: %d", len(a))
|
||||
}
|
||||
|
||||
inMap := func(val interface{}) bool {
|
||||
for _, v := range a {
|
||||
if reflect.DeepEqual(v, val) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
for _, val := range []interface{}{"a-value", 2, true} {
|
||||
if !inMap(val) {
|
||||
t.Errorf("Map should have the value %v", val)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestMap_Tag(t *testing.T) {
|
||||
var T = struct {
|
||||
A string `structs:"x"`
|
||||
B int `structs:"y"`
|
||||
C bool `structs:"z"`
|
||||
}{
|
||||
A: "a-value",
|
||||
B: 2,
|
||||
C: true,
|
||||
}
|
||||
|
||||
a := Map(T)
|
||||
|
||||
inMap := func(key interface{}) bool {
|
||||
for k := range a {
|
||||
if reflect.DeepEqual(k, key) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
for _, key := range []string{"x", "y", "z"} {
|
||||
if !inMap(key) {
|
||||
t.Errorf("Map should have the key %v", key)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestMap_CustomTag(t *testing.T) {
|
||||
var T = struct {
|
||||
A string `dd:"x"`
|
||||
B int `dd:"y"`
|
||||
C bool `dd:"z"`
|
||||
}{
|
||||
A: "a-value",
|
||||
B: 2,
|
||||
C: true,
|
||||
}
|
||||
|
||||
s := New(T)
|
||||
s.TagName = "dd"
|
||||
|
||||
a := s.Map()
|
||||
|
||||
inMap := func(key interface{}) bool {
|
||||
for k := range a {
|
||||
if reflect.DeepEqual(k, key) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
for _, key := range []string{"x", "y", "z"} {
|
||||
if !inMap(key) {
|
||||
t.Errorf("Map should have the key %v", key)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestMap_MultipleCustomTag(t *testing.T) {
|
||||
var A = struct {
|
||||
X string `aa:"ax"`
|
||||
}{"a_value"}
|
||||
|
||||
aStruct := New(A)
|
||||
aStruct.TagName = "aa"
|
||||
|
||||
var B = struct {
|
||||
X string `bb:"bx"`
|
||||
}{"b_value"}
|
||||
|
||||
bStruct := New(B)
|
||||
bStruct.TagName = "bb"
|
||||
|
||||
a, b := aStruct.Map(), bStruct.Map()
|
||||
if !reflect.DeepEqual(a, map[string]interface{}{"ax": "a_value"}) {
|
||||
t.Error("Map should have field ax with value a_value")
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(b, map[string]interface{}{"bx": "b_value"}) {
|
||||
t.Error("Map should have field bx with value b_value")
|
||||
}
|
||||
}
|
||||
|
||||
func TestMap_OmitEmpty(t *testing.T) {
|
||||
type A struct {
|
||||
Name string
|
||||
Value string `structs:",omitempty"`
|
||||
Time time.Time `structs:",omitempty"`
|
||||
}
|
||||
a := A{}
|
||||
|
||||
m := Map(a)
|
||||
|
||||
_, ok := m["Value"].(map[string]interface{})
|
||||
if ok {
|
||||
t.Error("Map should not contain the Value field that is tagged as omitempty")
|
||||
}
|
||||
|
||||
_, ok = m["Time"].(map[string]interface{})
|
||||
if ok {
|
||||
t.Error("Map should not contain the Time field that is tagged as omitempty")
|
||||
}
|
||||
}
|
||||
|
||||
func TestMap_OmitNested(t *testing.T) {
|
||||
type A struct {
|
||||
Name string
|
||||
Value string
|
||||
Time time.Time `structs:",omitnested"`
|
||||
}
|
||||
a := A{Time: time.Now()}
|
||||
|
||||
type B struct {
|
||||
Desc string
|
||||
A A
|
||||
}
|
||||
b := &B{A: a}
|
||||
|
||||
m := Map(b)
|
||||
|
||||
in, ok := m["A"].(map[string]interface{})
|
||||
if !ok {
|
||||
t.Error("Map nested structs is not available in the map")
|
||||
}
|
||||
|
||||
// should not happen
|
||||
if _, ok := in["Time"].(map[string]interface{}); ok {
|
||||
t.Error("Map nested struct should omit recursiving parsing of Time")
|
||||
}
|
||||
|
||||
if _, ok := in["Time"].(time.Time); !ok {
|
||||
t.Error("Map nested struct should stop parsing of Time at is current value")
|
||||
}
|
||||
}
|
||||
|
||||
func TestMap_Nested(t *testing.T) {
|
||||
type A struct {
|
||||
Name string
|
||||
}
|
||||
a := &A{Name: "example"}
|
||||
|
||||
type B struct {
|
||||
A *A
|
||||
}
|
||||
b := &B{A: a}
|
||||
|
||||
m := Map(b)
|
||||
|
||||
if typ := reflect.TypeOf(m).Kind(); typ != reflect.Map {
|
||||
t.Errorf("Map should return a map type, got: %v", typ)
|
||||
}
|
||||
|
||||
in, ok := m["A"].(map[string]interface{})
|
||||
if !ok {
|
||||
t.Error("Map nested structs is not available in the map")
|
||||
}
|
||||
|
||||
if name := in["Name"].(string); name != "example" {
|
||||
t.Errorf("Map nested struct's name field should give example, got: %s", name)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMap_Anonymous(t *testing.T) {
|
||||
type A struct {
|
||||
Name string
|
||||
}
|
||||
a := &A{Name: "example"}
|
||||
|
||||
type B struct {
|
||||
*A
|
||||
}
|
||||
b := &B{}
|
||||
b.A = a
|
||||
|
||||
m := Map(b)
|
||||
|
||||
if typ := reflect.TypeOf(m).Kind(); typ != reflect.Map {
|
||||
t.Errorf("Map should return a map type, got: %v", typ)
|
||||
}
|
||||
|
||||
in, ok := m["A"].(map[string]interface{})
|
||||
if !ok {
|
||||
t.Error("Embedded structs is not available in the map")
|
||||
}
|
||||
|
||||
if name := in["Name"].(string); name != "example" {
|
||||
t.Errorf("Embedded A struct's Name field should give example, got: %s", name)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStruct(t *testing.T) {
|
||||
var T = struct{}{}
|
||||
|
||||
if !IsStruct(T) {
|
||||
t.Errorf("T should be a struct, got: %T", T)
|
||||
}
|
||||
|
||||
if !IsStruct(&T) {
|
||||
t.Errorf("T should be a struct, got: %T", T)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestValues(t *testing.T) {
|
||||
var T = struct {
|
||||
A string
|
||||
B int
|
||||
C bool
|
||||
}{
|
||||
A: "a-value",
|
||||
B: 2,
|
||||
C: true,
|
||||
}
|
||||
|
||||
s := Values(T)
|
||||
|
||||
if typ := reflect.TypeOf(s).Kind(); typ != reflect.Slice {
|
||||
t.Errorf("Values should return a slice type, got: %v", typ)
|
||||
}
|
||||
|
||||
inSlice := func(val interface{}) bool {
|
||||
for _, v := range s {
|
||||
if reflect.DeepEqual(v, val) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
for _, val := range []interface{}{"a-value", 2, true} {
|
||||
if !inSlice(val) {
|
||||
t.Errorf("Values should have the value %v", val)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestValues_OmitEmpty(t *testing.T) {
|
||||
type A struct {
|
||||
Name string
|
||||
Value int `structs:",omitempty"`
|
||||
}
|
||||
|
||||
a := A{Name: "example"}
|
||||
s := Values(a)
|
||||
|
||||
if len(s) != 1 {
|
||||
t.Errorf("Values of omitted empty fields should be not counted")
|
||||
}
|
||||
|
||||
if s[0].(string) != "example" {
|
||||
t.Errorf("Values of omitted empty fields should left the value example")
|
||||
}
|
||||
}
|
||||
|
||||
func TestValues_OmitNested(t *testing.T) {
|
||||
type A struct {
|
||||
Name string
|
||||
Value int
|
||||
}
|
||||
|
||||
a := A{
|
||||
Name: "example",
|
||||
Value: 123,
|
||||
}
|
||||
|
||||
type B struct {
|
||||
A A `structs:",omitnested"`
|
||||
C int
|
||||
}
|
||||
b := &B{A: a, C: 123}
|
||||
|
||||
s := Values(b)
|
||||
|
||||
if len(s) != 2 {
|
||||
t.Errorf("Values of omitted nested struct should be not counted")
|
||||
}
|
||||
|
||||
inSlice := func(val interface{}) bool {
|
||||
for _, v := range s {
|
||||
if reflect.DeepEqual(v, val) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
for _, val := range []interface{}{123, a} {
|
||||
if !inSlice(val) {
|
||||
t.Errorf("Values should have the value %v", val)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestValues_Nested(t *testing.T) {
|
||||
type A struct {
|
||||
Name string
|
||||
}
|
||||
a := A{Name: "example"}
|
||||
|
||||
type B struct {
|
||||
A A
|
||||
C int
|
||||
}
|
||||
b := &B{A: a, C: 123}
|
||||
|
||||
s := Values(b)
|
||||
|
||||
inSlice := func(val interface{}) bool {
|
||||
for _, v := range s {
|
||||
if reflect.DeepEqual(v, val) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
for _, val := range []interface{}{"example", 123} {
|
||||
if !inSlice(val) {
|
||||
t.Errorf("Values should have the value %v", val)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestValues_Anonymous(t *testing.T) {
|
||||
type A struct {
|
||||
Name string
|
||||
}
|
||||
a := A{Name: "example"}
|
||||
|
||||
type B struct {
|
||||
A
|
||||
C int
|
||||
}
|
||||
b := &B{C: 123}
|
||||
b.A = a
|
||||
|
||||
s := Values(b)
|
||||
|
||||
inSlice := func(val interface{}) bool {
|
||||
for _, v := range s {
|
||||
if reflect.DeepEqual(v, val) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
for _, val := range []interface{}{"example", 123} {
|
||||
if !inSlice(val) {
|
||||
t.Errorf("Values should have the value %v", val)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestFields(t *testing.T) {
|
||||
var T = struct {
|
||||
A string
|
||||
B int
|
||||
C bool
|
||||
}{
|
||||
A: "a-value",
|
||||
B: 2,
|
||||
C: true,
|
||||
}
|
||||
|
||||
s := Fields(T)
|
||||
|
||||
if len(s) != 3 {
|
||||
t.Errorf("Fields should return a slice of len 3, got: %d", len(s))
|
||||
}
|
||||
|
||||
inSlice := func(val string) bool {
|
||||
for _, v := range s {
|
||||
if reflect.DeepEqual(v.Name(), val) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
for _, val := range []string{"A", "B", "C"} {
|
||||
if !inSlice(val) {
|
||||
t.Errorf("Fields should have the value %v", val)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestFields_OmitNested(t *testing.T) {
|
||||
type A struct {
|
||||
Name string
|
||||
Enabled bool
|
||||
}
|
||||
a := A{Name: "example"}
|
||||
|
||||
type B struct {
|
||||
A A
|
||||
C int
|
||||
Value string `structs:"-"`
|
||||
Number int
|
||||
}
|
||||
b := &B{A: a, C: 123}
|
||||
|
||||
s := Fields(b)
|
||||
|
||||
if len(s) != 3 {
|
||||
t.Errorf("Fields should omit nested struct. Expecting 2 got: %d", len(s))
|
||||
}
|
||||
|
||||
inSlice := func(val interface{}) bool {
|
||||
for _, v := range s {
|
||||
if reflect.DeepEqual(v.Name(), val) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
for _, val := range []interface{}{"A", "C"} {
|
||||
if !inSlice(val) {
|
||||
t.Errorf("Fields should have the value %v", val)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestFields_Anonymous(t *testing.T) {
|
||||
type A struct {
|
||||
Name string
|
||||
}
|
||||
a := A{Name: "example"}
|
||||
|
||||
type B struct {
|
||||
A
|
||||
C int
|
||||
}
|
||||
b := &B{C: 123}
|
||||
b.A = a
|
||||
|
||||
s := Fields(b)
|
||||
|
||||
inSlice := func(val interface{}) bool {
|
||||
for _, v := range s {
|
||||
if reflect.DeepEqual(v.Name(), val) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
for _, val := range []interface{}{"A", "C"} {
|
||||
if !inSlice(val) {
|
||||
t.Errorf("Fields should have the value %v", val)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsZero(t *testing.T) {
|
||||
var T = struct {
|
||||
A string
|
||||
B int
|
||||
C bool `structs:"-"`
|
||||
D []string
|
||||
}{}
|
||||
|
||||
ok := IsZero(T)
|
||||
if !ok {
|
||||
t.Error("IsZero should return true because none of the fields are initialized.")
|
||||
}
|
||||
|
||||
var X = struct {
|
||||
A string
|
||||
F *bool
|
||||
}{
|
||||
A: "a-value",
|
||||
}
|
||||
|
||||
ok = IsZero(X)
|
||||
if ok {
|
||||
t.Error("IsZero should return false because A is initialized")
|
||||
}
|
||||
|
||||
var Y = struct {
|
||||
A string
|
||||
B int
|
||||
}{
|
||||
A: "a-value",
|
||||
B: 123,
|
||||
}
|
||||
|
||||
ok = IsZero(Y)
|
||||
if ok {
|
||||
t.Error("IsZero should return false because A and B is initialized")
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsZero_OmitNested(t *testing.T) {
|
||||
type A struct {
|
||||
Name string
|
||||
D string
|
||||
}
|
||||
a := A{Name: "example"}
|
||||
|
||||
type B struct {
|
||||
A A `structs:",omitnested"`
|
||||
C int
|
||||
}
|
||||
b := &B{A: a, C: 123}
|
||||
|
||||
ok := IsZero(b)
|
||||
if ok {
|
||||
t.Error("IsZero should return false because A, B and C are initialized")
|
||||
}
|
||||
|
||||
aZero := A{}
|
||||
bZero := &B{A: aZero}
|
||||
|
||||
ok = IsZero(bZero)
|
||||
if !ok {
|
||||
t.Error("IsZero should return true because neither A nor B is initialized")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestIsZero_Nested(t *testing.T) {
|
||||
type A struct {
|
||||
Name string
|
||||
D string
|
||||
}
|
||||
a := A{Name: "example"}
|
||||
|
||||
type B struct {
|
||||
A A
|
||||
C int
|
||||
}
|
||||
b := &B{A: a, C: 123}
|
||||
|
||||
ok := IsZero(b)
|
||||
if ok {
|
||||
t.Error("IsZero should return false because A, B and C are initialized")
|
||||
}
|
||||
|
||||
aZero := A{}
|
||||
bZero := &B{A: aZero}
|
||||
|
||||
ok = IsZero(bZero)
|
||||
if !ok {
|
||||
t.Error("IsZero should return true because neither A nor B is initialized")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestIsZero_Anonymous(t *testing.T) {
|
||||
type A struct {
|
||||
Name string
|
||||
D string
|
||||
}
|
||||
a := A{Name: "example"}
|
||||
|
||||
type B struct {
|
||||
A
|
||||
C int
|
||||
}
|
||||
b := &B{C: 123}
|
||||
b.A = a
|
||||
|
||||
ok := IsZero(b)
|
||||
if ok {
|
||||
t.Error("IsZero should return false because A, B and C are initialized")
|
||||
}
|
||||
|
||||
aZero := A{}
|
||||
bZero := &B{}
|
||||
bZero.A = aZero
|
||||
|
||||
ok = IsZero(bZero)
|
||||
if !ok {
|
||||
t.Error("IsZero should return true because neither A nor B is initialized")
|
||||
}
|
||||
}
|
||||
|
||||
func TestHasZero(t *testing.T) {
|
||||
var T = struct {
|
||||
A string
|
||||
B int
|
||||
C bool `structs:"-"`
|
||||
D []string
|
||||
}{
|
||||
A: "a-value",
|
||||
B: 2,
|
||||
}
|
||||
|
||||
ok := HasZero(T)
|
||||
if !ok {
|
||||
t.Error("HasZero should return true because A and B are initialized.")
|
||||
}
|
||||
|
||||
var X = struct {
|
||||
A string
|
||||
F *bool
|
||||
}{
|
||||
A: "a-value",
|
||||
}
|
||||
|
||||
ok = HasZero(X)
|
||||
if !ok {
|
||||
t.Error("HasZero should return true because A is initialized")
|
||||
}
|
||||
|
||||
var Y = struct {
|
||||
A string
|
||||
B int
|
||||
}{
|
||||
A: "a-value",
|
||||
B: 123,
|
||||
}
|
||||
|
||||
ok = HasZero(Y)
|
||||
if ok {
|
||||
t.Error("HasZero should return false because A and B is initialized")
|
||||
}
|
||||
}
|
||||
|
||||
func TestHasZero_OmitNested(t *testing.T) {
|
||||
type A struct {
|
||||
Name string
|
||||
D string
|
||||
}
|
||||
a := A{Name: "example"}
|
||||
|
||||
type B struct {
|
||||
A A `structs:",omitnested"`
|
||||
C int
|
||||
}
|
||||
b := &B{A: a, C: 123}
|
||||
|
||||
// Because the Field A inside B is omitted HasZero should return false
|
||||
// because it will stop iterating deeper andnot going to lookup for D
|
||||
ok := HasZero(b)
|
||||
if ok {
|
||||
t.Error("HasZero should return false because A and C are initialized")
|
||||
}
|
||||
}
|
||||
|
||||
func TestHasZero_Nested(t *testing.T) {
|
||||
type A struct {
|
||||
Name string
|
||||
D string
|
||||
}
|
||||
a := A{Name: "example"}
|
||||
|
||||
type B struct {
|
||||
A A
|
||||
C int
|
||||
}
|
||||
b := &B{A: a, C: 123}
|
||||
|
||||
ok := HasZero(b)
|
||||
if !ok {
|
||||
t.Error("HasZero should return true because D is not initialized")
|
||||
}
|
||||
}
|
||||
|
||||
func TestHasZero_Anonymous(t *testing.T) {
|
||||
type A struct {
|
||||
Name string
|
||||
D string
|
||||
}
|
||||
a := A{Name: "example"}
|
||||
|
||||
type B struct {
|
||||
A
|
||||
C int
|
||||
}
|
||||
b := &B{C: 123}
|
||||
b.A = a
|
||||
|
||||
ok := HasZero(b)
|
||||
if !ok {
|
||||
t.Error("HasZero should return false because D is not initialized")
|
||||
}
|
||||
}
|
||||
|
||||
func TestName(t *testing.T) {
|
||||
type Foo struct {
|
||||
A string
|
||||
B bool
|
||||
}
|
||||
f := &Foo{}
|
||||
|
||||
n := Name(f)
|
||||
if n != "Foo" {
|
||||
t.Errorf("Name should return Foo, got: %s", n)
|
||||
}
|
||||
|
||||
unnamed := struct{ Name string }{Name: "Cihangir"}
|
||||
m := Name(unnamed)
|
||||
if m != "" {
|
||||
t.Errorf("Name should return empty string for unnamed struct, got: %s", n)
|
||||
}
|
||||
|
||||
defer func() {
|
||||
err := recover()
|
||||
if err == nil {
|
||||
t.Error("Name should panic if a non struct is passed")
|
||||
}
|
||||
}()
|
||||
|
||||
Name([]string{})
|
||||
}
|
||||
|
||||
func TestNestedNilPointer(t *testing.T) {
|
||||
type Collar struct {
|
||||
Engraving string
|
||||
}
|
||||
|
||||
type Dog struct {
|
||||
Name string
|
||||
Collar *Collar
|
||||
}
|
||||
|
||||
type Person struct {
|
||||
Name string
|
||||
Dog *Dog
|
||||
}
|
||||
|
||||
person := &Person{
|
||||
Name: "John",
|
||||
}
|
||||
|
||||
personWithDog := &Person{
|
||||
Name: "Ron",
|
||||
Dog: &Dog{
|
||||
Name: "Rover",
|
||||
},
|
||||
}
|
||||
|
||||
personWithDogWithCollar := &Person{
|
||||
Name: "Kon",
|
||||
Dog: &Dog{
|
||||
Name: "Ruffles",
|
||||
Collar: &Collar{
|
||||
Engraving: "If lost, call Kon",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
defer func() {
|
||||
err := recover()
|
||||
if err != nil {
|
||||
fmt.Printf("err %+v\n", err)
|
||||
t.Error("Internal nil pointer should not panic")
|
||||
}
|
||||
}()
|
||||
|
||||
_ = Map(person) // Panics
|
||||
_ = Map(personWithDog) // Panics
|
||||
_ = Map(personWithDogWithCollar) // Doesn't panic
|
||||
}
|
46
Godeps/_workspace/src/github.com/fatih/structs/tags_test.go
generated
vendored
46
Godeps/_workspace/src/github.com/fatih/structs/tags_test.go
generated
vendored
@ -1,46 +0,0 @@
|
||||
package structs
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestParseTag_Name(t *testing.T) {
|
||||
tags := []struct {
|
||||
tag string
|
||||
has bool
|
||||
}{
|
||||
{"", false},
|
||||
{"name", true},
|
||||
{"name,opt", true},
|
||||
{"name , opt, opt2", false}, // has a single whitespace
|
||||
{", opt, opt2", false},
|
||||
}
|
||||
|
||||
for _, tag := range tags {
|
||||
name, _ := parseTag(tag.tag)
|
||||
|
||||
if (name != "name") && tag.has {
|
||||
t.Errorf("Parse tag should return name: %#v", tag)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseTag_Opts(t *testing.T) {
|
||||
tags := []struct {
|
||||
opts string
|
||||
has bool
|
||||
}{
|
||||
{"name", false},
|
||||
{"name,opt", true},
|
||||
{"name , opt, opt2", false}, // has a single whitespace
|
||||
{",opt, opt2", true},
|
||||
{", opt3, opt4", false},
|
||||
}
|
||||
|
||||
// search for "opt"
|
||||
for _, tag := range tags {
|
||||
_, opts := parseTag(tag.opts)
|
||||
|
||||
if opts.Has("opt") != tag.has {
|
||||
t.Errorf("Tag opts should have opt: %#v", tag)
|
||||
}
|
||||
}
|
||||
}
|
7
Godeps/_workspace/src/github.com/gorilla/context/.travis.yml
generated
vendored
7
Godeps/_workspace/src/github.com/gorilla/context/.travis.yml
generated
vendored
@ -1,7 +0,0 @@
|
||||
language: go
|
||||
|
||||
go:
|
||||
- 1.0
|
||||
- 1.1
|
||||
- 1.2
|
||||
- tip
|
161
Godeps/_workspace/src/github.com/gorilla/context/context_test.go
generated
vendored
161
Godeps/_workspace/src/github.com/gorilla/context/context_test.go
generated
vendored
@ -1,161 +0,0 @@
|
||||
// Copyright 2012 The Gorilla Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package context
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type keyType int
|
||||
|
||||
const (
|
||||
key1 keyType = iota
|
||||
key2
|
||||
)
|
||||
|
||||
func TestContext(t *testing.T) {
|
||||
assertEqual := func(val interface{}, exp interface{}) {
|
||||
if val != exp {
|
||||
t.Errorf("Expected %v, got %v.", exp, val)
|
||||
}
|
||||
}
|
||||
|
||||
r, _ := http.NewRequest("GET", "http://localhost:8080/", nil)
|
||||
emptyR, _ := http.NewRequest("GET", "http://localhost:8080/", nil)
|
||||
|
||||
// Get()
|
||||
assertEqual(Get(r, key1), nil)
|
||||
|
||||
// Set()
|
||||
Set(r, key1, "1")
|
||||
assertEqual(Get(r, key1), "1")
|
||||
assertEqual(len(data[r]), 1)
|
||||
|
||||
Set(r, key2, "2")
|
||||
assertEqual(Get(r, key2), "2")
|
||||
assertEqual(len(data[r]), 2)
|
||||
|
||||
//GetOk
|
||||
value, ok := GetOk(r, key1)
|
||||
assertEqual(value, "1")
|
||||
assertEqual(ok, true)
|
||||
|
||||
value, ok = GetOk(r, "not exists")
|
||||
assertEqual(value, nil)
|
||||
assertEqual(ok, false)
|
||||
|
||||
Set(r, "nil value", nil)
|
||||
value, ok = GetOk(r, "nil value")
|
||||
assertEqual(value, nil)
|
||||
assertEqual(ok, true)
|
||||
|
||||
// GetAll()
|
||||
values := GetAll(r)
|
||||
assertEqual(len(values), 3)
|
||||
|
||||
// GetAll() for empty request
|
||||
values = GetAll(emptyR)
|
||||
if values != nil {
|
||||
t.Error("GetAll didn't return nil value for invalid request")
|
||||
}
|
||||
|
||||
// GetAllOk()
|
||||
values, ok = GetAllOk(r)
|
||||
assertEqual(len(values), 3)
|
||||
assertEqual(ok, true)
|
||||
|
||||
// GetAllOk() for empty request
|
||||
values, ok = GetAllOk(emptyR)
|
||||
assertEqual(value, nil)
|
||||
assertEqual(ok, false)
|
||||
|
||||
// Delete()
|
||||
Delete(r, key1)
|
||||
assertEqual(Get(r, key1), nil)
|
||||
assertEqual(len(data[r]), 2)
|
||||
|
||||
Delete(r, key2)
|
||||
assertEqual(Get(r, key2), nil)
|
||||
assertEqual(len(data[r]), 1)
|
||||
|
||||
// Clear()
|
||||
Clear(r)
|
||||
assertEqual(len(data), 0)
|
||||
}
|
||||
|
||||
func parallelReader(r *http.Request, key string, iterations int, wait, done chan struct{}) {
|
||||
<-wait
|
||||
for i := 0; i < iterations; i++ {
|
||||
Get(r, key)
|
||||
}
|
||||
done <- struct{}{}
|
||||
|
||||
}
|
||||
|
||||
func parallelWriter(r *http.Request, key, value string, iterations int, wait, done chan struct{}) {
|
||||
<-wait
|
||||
for i := 0; i < iterations; i++ {
|
||||
Set(r, key, value)
|
||||
}
|
||||
done <- struct{}{}
|
||||
|
||||
}
|
||||
|
||||
func benchmarkMutex(b *testing.B, numReaders, numWriters, iterations int) {
|
||||
|
||||
b.StopTimer()
|
||||
r, _ := http.NewRequest("GET", "http://localhost:8080/", nil)
|
||||
done := make(chan struct{})
|
||||
b.StartTimer()
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
wait := make(chan struct{})
|
||||
|
||||
for i := 0; i < numReaders; i++ {
|
||||
go parallelReader(r, "test", iterations, wait, done)
|
||||
}
|
||||
|
||||
for i := 0; i < numWriters; i++ {
|
||||
go parallelWriter(r, "test", "123", iterations, wait, done)
|
||||
}
|
||||
|
||||
close(wait)
|
||||
|
||||
for i := 0; i < numReaders+numWriters; i++ {
|
||||
<-done
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func BenchmarkMutexSameReadWrite1(b *testing.B) {
|
||||
benchmarkMutex(b, 1, 1, 32)
|
||||
}
|
||||
func BenchmarkMutexSameReadWrite2(b *testing.B) {
|
||||
benchmarkMutex(b, 2, 2, 32)
|
||||
}
|
||||
func BenchmarkMutexSameReadWrite4(b *testing.B) {
|
||||
benchmarkMutex(b, 4, 4, 32)
|
||||
}
|
||||
func BenchmarkMutex1(b *testing.B) {
|
||||
benchmarkMutex(b, 2, 8, 32)
|
||||
}
|
||||
func BenchmarkMutex2(b *testing.B) {
|
||||
benchmarkMutex(b, 16, 4, 64)
|
||||
}
|
||||
func BenchmarkMutex3(b *testing.B) {
|
||||
benchmarkMutex(b, 1, 2, 128)
|
||||
}
|
||||
func BenchmarkMutex4(b *testing.B) {
|
||||
benchmarkMutex(b, 128, 32, 256)
|
||||
}
|
||||
func BenchmarkMutex5(b *testing.B) {
|
||||
benchmarkMutex(b, 1024, 2048, 64)
|
||||
}
|
||||
func BenchmarkMutex6(b *testing.B) {
|
||||
benchmarkMutex(b, 2048, 1024, 512)
|
||||
}
|
7
Godeps/_workspace/src/github.com/gorilla/mux/.travis.yml
generated
vendored
7
Godeps/_workspace/src/github.com/gorilla/mux/.travis.yml
generated
vendored
@ -1,7 +0,0 @@
|
||||
language: go
|
||||
|
||||
go:
|
||||
- 1.0
|
||||
- 1.1
|
||||
- 1.2
|
||||
- tip
|
7
Godeps/_workspace/src/github.com/gorilla/mux/README.md
generated
vendored
7
Godeps/_workspace/src/github.com/gorilla/mux/README.md
generated
vendored
@ -1,7 +0,0 @@
|
||||
mux
|
||||
===
|
||||
[![Build Status](https://travis-ci.org/gorilla/mux.png?branch=master)](https://travis-ci.org/gorilla/mux)
|
||||
|
||||
gorilla/mux is a powerful URL router and dispatcher.
|
||||
|
||||
Read the full documentation here: http://www.gorillatoolkit.org/pkg/mux
|
21
Godeps/_workspace/src/github.com/gorilla/mux/bench_test.go
generated
vendored
21
Godeps/_workspace/src/github.com/gorilla/mux/bench_test.go
generated
vendored
@ -1,21 +0,0 @@
|
||||
// Copyright 2012 The Gorilla Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package mux
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func BenchmarkMux(b *testing.B) {
|
||||
router := new(Router)
|
||||
handler := func(w http.ResponseWriter, r *http.Request) {}
|
||||
router.HandleFunc("/v1/{v1}", handler)
|
||||
|
||||
request, _ := http.NewRequest("GET", "/v1/anything", nil)
|
||||
for i := 0; i < b.N; i++ {
|
||||
router.ServeHTTP(nil, request)
|
||||
}
|
||||
}
|
943
Godeps/_workspace/src/github.com/gorilla/mux/mux_test.go
generated
vendored
943
Godeps/_workspace/src/github.com/gorilla/mux/mux_test.go
generated
vendored
@ -1,943 +0,0 @@
|
||||
// Copyright 2012 The Gorilla Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package mux
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
"github.com/gorilla/context"
|
||||
)
|
||||
|
||||
type routeTest struct {
|
||||
title string // title of the test
|
||||
route *Route // the route being tested
|
||||
request *http.Request // a request to test the route
|
||||
vars map[string]string // the expected vars of the match
|
||||
host string // the expected host of the match
|
||||
path string // the expected path of the match
|
||||
shouldMatch bool // whether the request is expected to match the route at all
|
||||
shouldRedirect bool // whether the request should result in a redirect
|
||||
}
|
||||
|
||||
func TestHost(t *testing.T) {
|
||||
// newRequestHost a new request with a method, url, and host header
|
||||
newRequestHost := func(method, url, host string) *http.Request {
|
||||
req, err := http.NewRequest(method, url, nil)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
req.Host = host
|
||||
return req
|
||||
}
|
||||
|
||||
tests := []routeTest{
|
||||
{
|
||||
title: "Host route match",
|
||||
route: new(Route).Host("aaa.bbb.ccc"),
|
||||
request: newRequest("GET", "http://aaa.bbb.ccc/111/222/333"),
|
||||
vars: map[string]string{},
|
||||
host: "aaa.bbb.ccc",
|
||||
path: "",
|
||||
shouldMatch: true,
|
||||
},
|
||||
{
|
||||
title: "Host route, wrong host in request URL",
|
||||
route: new(Route).Host("aaa.bbb.ccc"),
|
||||
request: newRequest("GET", "http://aaa.222.ccc/111/222/333"),
|
||||
vars: map[string]string{},
|
||||
host: "aaa.bbb.ccc",
|
||||
path: "",
|
||||
shouldMatch: false,
|
||||
},
|
||||
{
|
||||
title: "Host route with port, match",
|
||||
route: new(Route).Host("aaa.bbb.ccc:1234"),
|
||||
request: newRequest("GET", "http://aaa.bbb.ccc:1234/111/222/333"),
|
||||
vars: map[string]string{},
|
||||
host: "aaa.bbb.ccc:1234",
|
||||
path: "",
|
||||
shouldMatch: true,
|
||||
},
|
||||
{
|
||||
title: "Host route with port, wrong port in request URL",
|
||||
route: new(Route).Host("aaa.bbb.ccc:1234"),
|
||||
request: newRequest("GET", "http://aaa.bbb.ccc:9999/111/222/333"),
|
||||
vars: map[string]string{},
|
||||
host: "aaa.bbb.ccc:1234",
|
||||
path: "",
|
||||
shouldMatch: false,
|
||||
},
|
||||
{
|
||||
title: "Host route, match with host in request header",
|
||||
route: new(Route).Host("aaa.bbb.ccc"),
|
||||
request: newRequestHost("GET", "/111/222/333", "aaa.bbb.ccc"),
|
||||
vars: map[string]string{},
|
||||
host: "aaa.bbb.ccc",
|
||||
path: "",
|
||||
shouldMatch: true,
|
||||
},
|
||||
{
|
||||
title: "Host route, wrong host in request header",
|
||||
route: new(Route).Host("aaa.bbb.ccc"),
|
||||
request: newRequestHost("GET", "/111/222/333", "aaa.222.ccc"),
|
||||
vars: map[string]string{},
|
||||
host: "aaa.bbb.ccc",
|
||||
path: "",
|
||||
shouldMatch: false,
|
||||
},
|
||||
// BUG {new(Route).Host("aaa.bbb.ccc:1234"), newRequestHost("GET", "/111/222/333", "aaa.bbb.ccc:1234"), map[string]string{}, "aaa.bbb.ccc:1234", "", true},
|
||||
{
|
||||
title: "Host route with port, wrong host in request header",
|
||||
route: new(Route).Host("aaa.bbb.ccc:1234"),
|
||||
request: newRequestHost("GET", "/111/222/333", "aaa.bbb.ccc:9999"),
|
||||
vars: map[string]string{},
|
||||
host: "aaa.bbb.ccc:1234",
|
||||
path: "",
|
||||
shouldMatch: false,
|
||||
},
|
||||
{
|
||||
title: "Host route with pattern, match",
|
||||
route: new(Route).Host("aaa.{v1:[a-z]{3}}.ccc"),
|
||||
request: newRequest("GET", "http://aaa.bbb.ccc/111/222/333"),
|
||||
vars: map[string]string{"v1": "bbb"},
|
||||
host: "aaa.bbb.ccc",
|
||||
path: "",
|
||||
shouldMatch: true,
|
||||
},
|
||||
{
|
||||
title: "Host route with pattern, wrong host in request URL",
|
||||
route: new(Route).Host("aaa.{v1:[a-z]{3}}.ccc"),
|
||||
request: newRequest("GET", "http://aaa.222.ccc/111/222/333"),
|
||||
vars: map[string]string{"v1": "bbb"},
|
||||
host: "aaa.bbb.ccc",
|
||||
path: "",
|
||||
shouldMatch: false,
|
||||
},
|
||||
{
|
||||
title: "Host route with multiple patterns, match",
|
||||
route: new(Route).Host("{v1:[a-z]{3}}.{v2:[a-z]{3}}.{v3:[a-z]{3}}"),
|
||||
request: newRequest("GET", "http://aaa.bbb.ccc/111/222/333"),
|
||||
vars: map[string]string{"v1": "aaa", "v2": "bbb", "v3": "ccc"},
|
||||
host: "aaa.bbb.ccc",
|
||||
path: "",
|
||||
shouldMatch: true,
|
||||
},
|
||||
{
|
||||
title: "Host route with multiple patterns, wrong host in request URL",
|
||||
route: new(Route).Host("{v1:[a-z]{3}}.{v2:[a-z]{3}}.{v3:[a-z]{3}}"),
|
||||
request: newRequest("GET", "http://aaa.222.ccc/111/222/333"),
|
||||
vars: map[string]string{"v1": "aaa", "v2": "bbb", "v3": "ccc"},
|
||||
host: "aaa.bbb.ccc",
|
||||
path: "",
|
||||
shouldMatch: false,
|
||||
},
|
||||
}
|
||||
for _, test := range tests {
|
||||
testRoute(t, test)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPath(t *testing.T) {
|
||||
tests := []routeTest{
|
||||
{
|
||||
title: "Path route, match",
|
||||
route: new(Route).Path("/111/222/333"),
|
||||
request: newRequest("GET", "http://localhost/111/222/333"),
|
||||
vars: map[string]string{},
|
||||
host: "",
|
||||
path: "/111/222/333",
|
||||
shouldMatch: true,
|
||||
},
|
||||
{
|
||||
title: "Path route, match with trailing slash in request and path",
|
||||
route: new(Route).Path("/111/"),
|
||||
request: newRequest("GET", "http://localhost/111/"),
|
||||
vars: map[string]string{},
|
||||
host: "",
|
||||
path: "/111/",
|
||||
shouldMatch: true,
|
||||
},
|
||||
{
|
||||
title: "Path route, do not match with trailing slash in path",
|
||||
route: new(Route).Path("/111/"),
|
||||
request: newRequest("GET", "http://localhost/111"),
|
||||
vars: map[string]string{},
|
||||
host: "",
|
||||
path: "/111",
|
||||
shouldMatch: false,
|
||||
},
|
||||
{
|
||||
title: "Path route, do not match with trailing slash in request",
|
||||
route: new(Route).Path("/111"),
|
||||
request: newRequest("GET", "http://localhost/111/"),
|
||||
vars: map[string]string{},
|
||||
host: "",
|
||||
path: "/111/",
|
||||
shouldMatch: false,
|
||||
},
|
||||
{
|
||||
title: "Path route, wrong path in request in request URL",
|
||||
route: new(Route).Path("/111/222/333"),
|
||||
request: newRequest("GET", "http://localhost/1/2/3"),
|
||||
vars: map[string]string{},
|
||||
host: "",
|
||||
path: "/111/222/333",
|
||||
shouldMatch: false,
|
||||
},
|
||||
{
|
||||
title: "Path route with pattern, match",
|
||||
route: new(Route).Path("/111/{v1:[0-9]{3}}/333"),
|
||||
request: newRequest("GET", "http://localhost/111/222/333"),
|
||||
vars: map[string]string{"v1": "222"},
|
||||
host: "",
|
||||
path: "/111/222/333",
|
||||
shouldMatch: true,
|
||||
},
|
||||
{
|
||||
title: "Path route with pattern, URL in request does not match",
|
||||
route: new(Route).Path("/111/{v1:[0-9]{3}}/333"),
|
||||
request: newRequest("GET", "http://localhost/111/aaa/333"),
|
||||
vars: map[string]string{"v1": "222"},
|
||||
host: "",
|
||||
path: "/111/222/333",
|
||||
shouldMatch: false,
|
||||
},
|
||||
{
|
||||
title: "Path route with multiple patterns, match",
|
||||
route: new(Route).Path("/{v1:[0-9]{3}}/{v2:[0-9]{3}}/{v3:[0-9]{3}}"),
|
||||
request: newRequest("GET", "http://localhost/111/222/333"),
|
||||
vars: map[string]string{"v1": "111", "v2": "222", "v3": "333"},
|
||||
host: "",
|
||||
path: "/111/222/333",
|
||||
shouldMatch: true,
|
||||
},
|
||||
{
|
||||
title: "Path route with multiple patterns, URL in request does not match",
|
||||
route: new(Route).Path("/{v1:[0-9]{3}}/{v2:[0-9]{3}}/{v3:[0-9]{3}}"),
|
||||
request: newRequest("GET", "http://localhost/111/aaa/333"),
|
||||
vars: map[string]string{"v1": "111", "v2": "222", "v3": "333"},
|
||||
host: "",
|
||||
path: "/111/222/333",
|
||||
shouldMatch: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
testRoute(t, test)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPathPrefix(t *testing.T) {
|
||||
tests := []routeTest{
|
||||
{
|
||||
title: "PathPrefix route, match",
|
||||
route: new(Route).PathPrefix("/111"),
|
||||
request: newRequest("GET", "http://localhost/111/222/333"),
|
||||
vars: map[string]string{},
|
||||
host: "",
|
||||
path: "/111",
|
||||
shouldMatch: true,
|
||||
},
|
||||
{
|
||||
title: "PathPrefix route, match substring",
|
||||
route: new(Route).PathPrefix("/1"),
|
||||
request: newRequest("GET", "http://localhost/111/222/333"),
|
||||
vars: map[string]string{},
|
||||
host: "",
|
||||
path: "/1",
|
||||
shouldMatch: true,
|
||||
},
|
||||
{
|
||||
title: "PathPrefix route, URL prefix in request does not match",
|
||||
route: new(Route).PathPrefix("/111"),
|
||||
request: newRequest("GET", "http://localhost/1/2/3"),
|
||||
vars: map[string]string{},
|
||||
host: "",
|
||||
path: "/111",
|
||||
shouldMatch: false,
|
||||
},
|
||||
{
|
||||
title: "PathPrefix route with pattern, match",
|
||||
route: new(Route).PathPrefix("/111/{v1:[0-9]{3}}"),
|
||||
request: newRequest("GET", "http://localhost/111/222/333"),
|
||||
vars: map[string]string{"v1": "222"},
|
||||
host: "",
|
||||
path: "/111/222",
|
||||
shouldMatch: true,
|
||||
},
|
||||
{
|
||||
title: "PathPrefix route with pattern, URL prefix in request does not match",
|
||||
route: new(Route).PathPrefix("/111/{v1:[0-9]{3}}"),
|
||||
request: newRequest("GET", "http://localhost/111/aaa/333"),
|
||||
vars: map[string]string{"v1": "222"},
|
||||
host: "",
|
||||
path: "/111/222",
|
||||
shouldMatch: false,
|
||||
},
|
||||
{
|
||||
title: "PathPrefix route with multiple patterns, match",
|
||||
route: new(Route).PathPrefix("/{v1:[0-9]{3}}/{v2:[0-9]{3}}"),
|
||||
request: newRequest("GET", "http://localhost/111/222/333"),
|
||||
vars: map[string]string{"v1": "111", "v2": "222"},
|
||||
host: "",
|
||||
path: "/111/222",
|
||||
shouldMatch: true,
|
||||
},
|
||||
{
|
||||
title: "PathPrefix route with multiple patterns, URL prefix in request does not match",
|
||||
route: new(Route).PathPrefix("/{v1:[0-9]{3}}/{v2:[0-9]{3}}"),
|
||||
request: newRequest("GET", "http://localhost/111/aaa/333"),
|
||||
vars: map[string]string{"v1": "111", "v2": "222"},
|
||||
host: "",
|
||||
path: "/111/222",
|
||||
shouldMatch: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
testRoute(t, test)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHostPath(t *testing.T) {
|
||||
tests := []routeTest{
|
||||
{
|
||||
title: "Host and Path route, match",
|
||||
route: new(Route).Host("aaa.bbb.ccc").Path("/111/222/333"),
|
||||
request: newRequest("GET", "http://aaa.bbb.ccc/111/222/333"),
|
||||
vars: map[string]string{},
|
||||
host: "",
|
||||
path: "",
|
||||
shouldMatch: true,
|
||||
},
|
||||
{
|
||||
title: "Host and Path route, wrong host in request URL",
|
||||
route: new(Route).Host("aaa.bbb.ccc").Path("/111/222/333"),
|
||||
request: newRequest("GET", "http://aaa.222.ccc/111/222/333"),
|
||||
vars: map[string]string{},
|
||||
host: "",
|
||||
path: "",
|
||||
shouldMatch: false,
|
||||
},
|
||||
{
|
||||
title: "Host and Path route with pattern, match",
|
||||
route: new(Route).Host("aaa.{v1:[a-z]{3}}.ccc").Path("/111/{v2:[0-9]{3}}/333"),
|
||||
request: newRequest("GET", "http://aaa.bbb.ccc/111/222/333"),
|
||||
vars: map[string]string{"v1": "bbb", "v2": "222"},
|
||||
host: "aaa.bbb.ccc",
|
||||
path: "/111/222/333",
|
||||
shouldMatch: true,
|
||||
},
|
||||
{
|
||||
title: "Host and Path route with pattern, URL in request does not match",
|
||||
route: new(Route).Host("aaa.{v1:[a-z]{3}}.ccc").Path("/111/{v2:[0-9]{3}}/333"),
|
||||
request: newRequest("GET", "http://aaa.222.ccc/111/222/333"),
|
||||
vars: map[string]string{"v1": "bbb", "v2": "222"},
|
||||
host: "aaa.bbb.ccc",
|
||||
path: "/111/222/333",
|
||||
shouldMatch: false,
|
||||
},
|
||||
{
|
||||
title: "Host and Path route with multiple patterns, match",
|
||||
route: new(Route).Host("{v1:[a-z]{3}}.{v2:[a-z]{3}}.{v3:[a-z]{3}}").Path("/{v4:[0-9]{3}}/{v5:[0-9]{3}}/{v6:[0-9]{3}}"),
|
||||
request: newRequest("GET", "http://aaa.bbb.ccc/111/222/333"),
|
||||
vars: map[string]string{"v1": "aaa", "v2": "bbb", "v3": "ccc", "v4": "111", "v5": "222", "v6": "333"},
|
||||
host: "aaa.bbb.ccc",
|
||||
path: "/111/222/333",
|
||||
shouldMatch: true,
|
||||
},
|
||||
{
|
||||
title: "Host and Path route with multiple patterns, URL in request does not match",
|
||||
route: new(Route).Host("{v1:[a-z]{3}}.{v2:[a-z]{3}}.{v3:[a-z]{3}}").Path("/{v4:[0-9]{3}}/{v5:[0-9]{3}}/{v6:[0-9]{3}}"),
|
||||
request: newRequest("GET", "http://aaa.222.ccc/111/222/333"),
|
||||
vars: map[string]string{"v1": "aaa", "v2": "bbb", "v3": "ccc", "v4": "111", "v5": "222", "v6": "333"},
|
||||
host: "aaa.bbb.ccc",
|
||||
path: "/111/222/333",
|
||||
shouldMatch: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
testRoute(t, test)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHeaders(t *testing.T) {
|
||||
// newRequestHeaders creates a new request with a method, url, and headers
|
||||
newRequestHeaders := func(method, url string, headers map[string]string) *http.Request {
|
||||
req, err := http.NewRequest(method, url, nil)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
for k, v := range headers {
|
||||
req.Header.Add(k, v)
|
||||
}
|
||||
return req
|
||||
}
|
||||
|
||||
tests := []routeTest{
|
||||
{
|
||||
title: "Headers route, match",
|
||||
route: new(Route).Headers("foo", "bar", "baz", "ding"),
|
||||
request: newRequestHeaders("GET", "http://localhost", map[string]string{"foo": "bar", "baz": "ding"}),
|
||||
vars: map[string]string{},
|
||||
host: "",
|
||||
path: "",
|
||||
shouldMatch: true,
|
||||
},
|
||||
{
|
||||
title: "Headers route, bad header values",
|
||||
route: new(Route).Headers("foo", "bar", "baz", "ding"),
|
||||
request: newRequestHeaders("GET", "http://localhost", map[string]string{"foo": "bar", "baz": "dong"}),
|
||||
vars: map[string]string{},
|
||||
host: "",
|
||||
path: "",
|
||||
shouldMatch: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
testRoute(t, test)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestMethods(t *testing.T) {
|
||||
tests := []routeTest{
|
||||
{
|
||||
title: "Methods route, match GET",
|
||||
route: new(Route).Methods("GET", "POST"),
|
||||
request: newRequest("GET", "http://localhost"),
|
||||
vars: map[string]string{},
|
||||
host: "",
|
||||
path: "",
|
||||
shouldMatch: true,
|
||||
},
|
||||
{
|
||||
title: "Methods route, match POST",
|
||||
route: new(Route).Methods("GET", "POST"),
|
||||
request: newRequest("POST", "http://localhost"),
|
||||
vars: map[string]string{},
|
||||
host: "",
|
||||
path: "",
|
||||
shouldMatch: true,
|
||||
},
|
||||
{
|
||||
title: "Methods route, bad method",
|
||||
route: new(Route).Methods("GET", "POST"),
|
||||
request: newRequest("PUT", "http://localhost"),
|
||||
vars: map[string]string{},
|
||||
host: "",
|
||||
path: "",
|
||||
shouldMatch: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
testRoute(t, test)
|
||||
}
|
||||
}
|
||||
|
||||
func TestQueries(t *testing.T) {
|
||||
tests := []routeTest{
|
||||
{
|
||||
title: "Queries route, match",
|
||||
route: new(Route).Queries("foo", "bar", "baz", "ding"),
|
||||
request: newRequest("GET", "http://localhost?foo=bar&baz=ding"),
|
||||
vars: map[string]string{},
|
||||
host: "",
|
||||
path: "",
|
||||
shouldMatch: true,
|
||||
},
|
||||
{
|
||||
title: "Queries route, match with a query string",
|
||||
route: new(Route).Host("www.example.com").Path("/api").Queries("foo", "bar", "baz", "ding"),
|
||||
request: newRequest("GET", "http://www.example.com/api?foo=bar&baz=ding"),
|
||||
vars: map[string]string{},
|
||||
host: "",
|
||||
path: "",
|
||||
shouldMatch: true,
|
||||
},
|
||||
{
|
||||
title: "Queries route, match with a query string out of order",
|
||||
route: new(Route).Host("www.example.com").Path("/api").Queries("foo", "bar", "baz", "ding"),
|
||||
request: newRequest("GET", "http://www.example.com/api?baz=ding&foo=bar"),
|
||||
vars: map[string]string{},
|
||||
host: "",
|
||||
path: "",
|
||||
shouldMatch: true,
|
||||
},
|
||||
{
|
||||
title: "Queries route, bad query",
|
||||
route: new(Route).Queries("foo", "bar", "baz", "ding"),
|
||||
request: newRequest("GET", "http://localhost?foo=bar&baz=dong"),
|
||||
vars: map[string]string{},
|
||||
host: "",
|
||||
path: "",
|
||||
shouldMatch: false,
|
||||
},
|
||||
{
|
||||
title: "Queries route with pattern, match",
|
||||
route: new(Route).Queries("foo", "{v1}"),
|
||||
request: newRequest("GET", "http://localhost?foo=bar"),
|
||||
vars: map[string]string{"v1": "bar"},
|
||||
host: "",
|
||||
path: "",
|
||||
shouldMatch: true,
|
||||
},
|
||||
{
|
||||
title: "Queries route with multiple patterns, match",
|
||||
route: new(Route).Queries("foo", "{v1}", "baz", "{v2}"),
|
||||
request: newRequest("GET", "http://localhost?foo=bar&baz=ding"),
|
||||
vars: map[string]string{"v1": "bar", "v2": "ding"},
|
||||
host: "",
|
||||
path: "",
|
||||
shouldMatch: true,
|
||||
},
|
||||
{
|
||||
title: "Queries route with regexp pattern, match",
|
||||
route: new(Route).Queries("foo", "{v1:[0-9]+}"),
|
||||
request: newRequest("GET", "http://localhost?foo=10"),
|
||||
vars: map[string]string{"v1": "10"},
|
||||
host: "",
|
||||
path: "",
|
||||
shouldMatch: true,
|
||||
},
|
||||
{
|
||||
title: "Queries route with regexp pattern, regexp does not match",
|
||||
route: new(Route).Queries("foo", "{v1:[0-9]+}"),
|
||||
request: newRequest("GET", "http://localhost?foo=a"),
|
||||
vars: map[string]string{},
|
||||
host: "",
|
||||
path: "",
|
||||
shouldMatch: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
testRoute(t, test)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSchemes(t *testing.T) {
|
||||
tests := []routeTest{
|
||||
// Schemes
|
||||
{
|
||||
title: "Schemes route, match https",
|
||||
route: new(Route).Schemes("https", "ftp"),
|
||||
request: newRequest("GET", "https://localhost"),
|
||||
vars: map[string]string{},
|
||||
host: "",
|
||||
path: "",
|
||||
shouldMatch: true,
|
||||
},
|
||||
{
|
||||
title: "Schemes route, match ftp",
|
||||
route: new(Route).Schemes("https", "ftp"),
|
||||
request: newRequest("GET", "ftp://localhost"),
|
||||
vars: map[string]string{},
|
||||
host: "",
|
||||
path: "",
|
||||
shouldMatch: true,
|
||||
},
|
||||
{
|
||||
title: "Schemes route, bad scheme",
|
||||
route: new(Route).Schemes("https", "ftp"),
|
||||
request: newRequest("GET", "http://localhost"),
|
||||
vars: map[string]string{},
|
||||
host: "",
|
||||
path: "",
|
||||
shouldMatch: false,
|
||||
},
|
||||
}
|
||||
for _, test := range tests {
|
||||
testRoute(t, test)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMatcherFunc(t *testing.T) {
|
||||
m := func(r *http.Request, m *RouteMatch) bool {
|
||||
if r.URL.Host == "aaa.bbb.ccc" {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
tests := []routeTest{
|
||||
{
|
||||
title: "MatchFunc route, match",
|
||||
route: new(Route).MatcherFunc(m),
|
||||
request: newRequest("GET", "http://aaa.bbb.ccc"),
|
||||
vars: map[string]string{},
|
||||
host: "",
|
||||
path: "",
|
||||
shouldMatch: true,
|
||||
},
|
||||
{
|
||||
title: "MatchFunc route, non-match",
|
||||
route: new(Route).MatcherFunc(m),
|
||||
request: newRequest("GET", "http://aaa.222.ccc"),
|
||||
vars: map[string]string{},
|
||||
host: "",
|
||||
path: "",
|
||||
shouldMatch: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
testRoute(t, test)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSubRouter(t *testing.T) {
|
||||
subrouter1 := new(Route).Host("{v1:[a-z]+}.google.com").Subrouter()
|
||||
subrouter2 := new(Route).PathPrefix("/foo/{v1}").Subrouter()
|
||||
|
||||
tests := []routeTest{
|
||||
{
|
||||
route: subrouter1.Path("/{v2:[a-z]+}"),
|
||||
request: newRequest("GET", "http://aaa.google.com/bbb"),
|
||||
vars: map[string]string{"v1": "aaa", "v2": "bbb"},
|
||||
host: "aaa.google.com",
|
||||
path: "/bbb",
|
||||
shouldMatch: true,
|
||||
},
|
||||
{
|
||||
route: subrouter1.Path("/{v2:[a-z]+}"),
|
||||
request: newRequest("GET", "http://111.google.com/111"),
|
||||
vars: map[string]string{"v1": "aaa", "v2": "bbb"},
|
||||
host: "aaa.google.com",
|
||||
path: "/bbb",
|
||||
shouldMatch: false,
|
||||
},
|
||||
{
|
||||
route: subrouter2.Path("/baz/{v2}"),
|
||||
request: newRequest("GET", "http://localhost/foo/bar/baz/ding"),
|
||||
vars: map[string]string{"v1": "bar", "v2": "ding"},
|
||||
host: "",
|
||||
path: "/foo/bar/baz/ding",
|
||||
shouldMatch: true,
|
||||
},
|
||||
{
|
||||
route: subrouter2.Path("/baz/{v2}"),
|
||||
request: newRequest("GET", "http://localhost/foo/bar"),
|
||||
vars: map[string]string{"v1": "bar", "v2": "ding"},
|
||||
host: "",
|
||||
path: "/foo/bar/baz/ding",
|
||||
shouldMatch: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
testRoute(t, test)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNamedRoutes(t *testing.T) {
|
||||
r1 := NewRouter()
|
||||
r1.NewRoute().Name("a")
|
||||
r1.NewRoute().Name("b")
|
||||
r1.NewRoute().Name("c")
|
||||
|
||||
r2 := r1.NewRoute().Subrouter()
|
||||
r2.NewRoute().Name("d")
|
||||
r2.NewRoute().Name("e")
|
||||
r2.NewRoute().Name("f")
|
||||
|
||||
r3 := r2.NewRoute().Subrouter()
|
||||
r3.NewRoute().Name("g")
|
||||
r3.NewRoute().Name("h")
|
||||
r3.NewRoute().Name("i")
|
||||
|
||||
if r1.namedRoutes == nil || len(r1.namedRoutes) != 9 {
|
||||
t.Errorf("Expected 9 named routes, got %v", r1.namedRoutes)
|
||||
} else if r1.Get("i") == nil {
|
||||
t.Errorf("Subroute name not registered")
|
||||
}
|
||||
}
|
||||
|
||||
func TestStrictSlash(t *testing.T) {
|
||||
r := NewRouter()
|
||||
r.StrictSlash(true)
|
||||
|
||||
tests := []routeTest{
|
||||
{
|
||||
title: "Redirect path without slash",
|
||||
route: r.NewRoute().Path("/111/"),
|
||||
request: newRequest("GET", "http://localhost/111"),
|
||||
vars: map[string]string{},
|
||||
host: "",
|
||||
path: "/111/",
|
||||
shouldMatch: true,
|
||||
shouldRedirect: true,
|
||||
},
|
||||
{
|
||||
title: "Do not redirect path with slash",
|
||||
route: r.NewRoute().Path("/111/"),
|
||||
request: newRequest("GET", "http://localhost/111/"),
|
||||
vars: map[string]string{},
|
||||
host: "",
|
||||
path: "/111/",
|
||||
shouldMatch: true,
|
||||
shouldRedirect: false,
|
||||
},
|
||||
{
|
||||
title: "Redirect path with slash",
|
||||
route: r.NewRoute().Path("/111"),
|
||||
request: newRequest("GET", "http://localhost/111/"),
|
||||
vars: map[string]string{},
|
||||
host: "",
|
||||
path: "/111",
|
||||
shouldMatch: true,
|
||||
shouldRedirect: true,
|
||||
},
|
||||
{
|
||||
title: "Do not redirect path without slash",
|
||||
route: r.NewRoute().Path("/111"),
|
||||
request: newRequest("GET", "http://localhost/111"),
|
||||
vars: map[string]string{},
|
||||
host: "",
|
||||
path: "/111",
|
||||
shouldMatch: true,
|
||||
shouldRedirect: false,
|
||||
},
|
||||
{
|
||||
title: "Propagate StrictSlash to subrouters",
|
||||
route: r.NewRoute().PathPrefix("/static/").Subrouter().Path("/images/"),
|
||||
request: newRequest("GET", "http://localhost/static/images"),
|
||||
vars: map[string]string{},
|
||||
host: "",
|
||||
path: "/static/images/",
|
||||
shouldMatch: true,
|
||||
shouldRedirect: true,
|
||||
},
|
||||
{
|
||||
title: "Ignore StrictSlash for path prefix",
|
||||
route: r.NewRoute().PathPrefix("/static/"),
|
||||
request: newRequest("GET", "http://localhost/static/logo.png"),
|
||||
vars: map[string]string{},
|
||||
host: "",
|
||||
path: "/static/",
|
||||
shouldMatch: true,
|
||||
shouldRedirect: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
testRoute(t, test)
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Helpers
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
func getRouteTemplate(route *Route) string {
|
||||
host, path := "none", "none"
|
||||
if route.regexp != nil {
|
||||
if route.regexp.host != nil {
|
||||
host = route.regexp.host.template
|
||||
}
|
||||
if route.regexp.path != nil {
|
||||
path = route.regexp.path.template
|
||||
}
|
||||
}
|
||||
return fmt.Sprintf("Host: %v, Path: %v", host, path)
|
||||
}
|
||||
|
||||
func testRoute(t *testing.T, test routeTest) {
|
||||
request := test.request
|
||||
route := test.route
|
||||
vars := test.vars
|
||||
shouldMatch := test.shouldMatch
|
||||
host := test.host
|
||||
path := test.path
|
||||
url := test.host + test.path
|
||||
shouldRedirect := test.shouldRedirect
|
||||
|
||||
var match RouteMatch
|
||||
ok := route.Match(request, &match)
|
||||
if ok != shouldMatch {
|
||||
msg := "Should match"
|
||||
if !shouldMatch {
|
||||
msg = "Should not match"
|
||||
}
|
||||
t.Errorf("(%v) %v:\nRoute: %#v\nRequest: %#v\nVars: %v\n", test.title, msg, route, request, vars)
|
||||
return
|
||||
}
|
||||
if shouldMatch {
|
||||
if test.vars != nil && !stringMapEqual(test.vars, match.Vars) {
|
||||
t.Errorf("(%v) Vars not equal: expected %v, got %v", test.title, vars, match.Vars)
|
||||
return
|
||||
}
|
||||
if host != "" {
|
||||
u, _ := test.route.URLHost(mapToPairs(match.Vars)...)
|
||||
if host != u.Host {
|
||||
t.Errorf("(%v) URLHost not equal: expected %v, got %v -- %v", test.title, host, u.Host, getRouteTemplate(route))
|
||||
return
|
||||
}
|
||||
}
|
||||
if path != "" {
|
||||
u, _ := route.URLPath(mapToPairs(match.Vars)...)
|
||||
if path != u.Path {
|
||||
t.Errorf("(%v) URLPath not equal: expected %v, got %v -- %v", test.title, path, u.Path, getRouteTemplate(route))
|
||||
return
|
||||
}
|
||||
}
|
||||
if url != "" {
|
||||
u, _ := route.URL(mapToPairs(match.Vars)...)
|
||||
if url != u.Host+u.Path {
|
||||
t.Errorf("(%v) URL not equal: expected %v, got %v -- %v", test.title, url, u.Host+u.Path, getRouteTemplate(route))
|
||||
return
|
||||
}
|
||||
}
|
||||
if shouldRedirect && match.Handler == nil {
|
||||
t.Errorf("(%v) Did not redirect", test.title)
|
||||
return
|
||||
}
|
||||
if !shouldRedirect && match.Handler != nil {
|
||||
t.Errorf("(%v) Unexpected redirect", test.title)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Tests that the context is cleared or not cleared properly depending on
|
||||
// the configuration of the router
|
||||
func TestKeepContext(t *testing.T) {
|
||||
func1 := func(w http.ResponseWriter, r *http.Request) {}
|
||||
|
||||
r := NewRouter()
|
||||
r.HandleFunc("/", func1).Name("func1")
|
||||
|
||||
req, _ := http.NewRequest("GET", "http://localhost/", nil)
|
||||
context.Set(req, "t", 1)
|
||||
|
||||
res := new(http.ResponseWriter)
|
||||
r.ServeHTTP(*res, req)
|
||||
|
||||
if _, ok := context.GetOk(req, "t"); ok {
|
||||
t.Error("Context should have been cleared at end of request")
|
||||
}
|
||||
|
||||
r.KeepContext = true
|
||||
|
||||
req, _ = http.NewRequest("GET", "http://localhost/", nil)
|
||||
context.Set(req, "t", 1)
|
||||
|
||||
r.ServeHTTP(*res, req)
|
||||
if _, ok := context.GetOk(req, "t"); !ok {
|
||||
t.Error("Context should NOT have been cleared at end of request")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
type TestA301ResponseWriter struct {
|
||||
hh http.Header
|
||||
status int
|
||||
}
|
||||
|
||||
func (ho TestA301ResponseWriter) Header() http.Header {
|
||||
return http.Header(ho.hh)
|
||||
}
|
||||
|
||||
func (ho TestA301ResponseWriter) Write(b []byte) (int, error) {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
func (ho TestA301ResponseWriter) WriteHeader(code int) {
|
||||
ho.status = code
|
||||
}
|
||||
|
||||
func Test301Redirect(t *testing.T) {
|
||||
m := make(http.Header)
|
||||
|
||||
func1 := func(w http.ResponseWriter, r *http.Request) {}
|
||||
func2 := func(w http.ResponseWriter, r *http.Request) {}
|
||||
|
||||
r := NewRouter()
|
||||
r.HandleFunc("/api/", func2).Name("func2")
|
||||
r.HandleFunc("/", func1).Name("func1")
|
||||
|
||||
req, _ := http.NewRequest("GET", "http://localhost//api/?abc=def", nil)
|
||||
|
||||
res := TestA301ResponseWriter{
|
||||
hh: m,
|
||||
status: 0,
|
||||
}
|
||||
r.ServeHTTP(&res, req)
|
||||
|
||||
if "http://localhost/api/?abc=def" != res.hh["Location"][0] {
|
||||
t.Errorf("Should have complete URL with query string")
|
||||
}
|
||||
}
|
||||
|
||||
// https://plus.google.com/101022900381697718949/posts/eWy6DjFJ6uW
|
||||
func TestSubrouterHeader(t *testing.T) {
|
||||
expected := "func1 response"
|
||||
func1 := func(w http.ResponseWriter, r *http.Request) {
|
||||
fmt.Fprint(w, expected)
|
||||
}
|
||||
func2 := func(http.ResponseWriter, *http.Request) {}
|
||||
|
||||
r := NewRouter()
|
||||
s := r.Headers("SomeSpecialHeader", "").Subrouter()
|
||||
s.HandleFunc("/", func1).Name("func1")
|
||||
r.HandleFunc("/", func2).Name("func2")
|
||||
|
||||
req, _ := http.NewRequest("GET", "http://localhost/", nil)
|
||||
req.Header.Add("SomeSpecialHeader", "foo")
|
||||
match := new(RouteMatch)
|
||||
matched := r.Match(req, match)
|
||||
if !matched {
|
||||
t.Errorf("Should match request")
|
||||
}
|
||||
if match.Route.GetName() != "func1" {
|
||||
t.Errorf("Expecting func1 handler, got %s", match.Route.GetName())
|
||||
}
|
||||
resp := NewRecorder()
|
||||
match.Handler.ServeHTTP(resp, req)
|
||||
if resp.Body.String() != expected {
|
||||
t.Errorf("Expecting %q", expected)
|
||||
}
|
||||
}
|
||||
|
||||
// mapToPairs converts a string map to a slice of string pairs
|
||||
func mapToPairs(m map[string]string) []string {
|
||||
var i int
|
||||
p := make([]string, len(m)*2)
|
||||
for k, v := range m {
|
||||
p[i] = k
|
||||
p[i+1] = v
|
||||
i += 2
|
||||
}
|
||||
return p
|
||||
}
|
||||
|
||||
// stringMapEqual checks the equality of two string maps
|
||||
func stringMapEqual(m1, m2 map[string]string) bool {
|
||||
nil1 := m1 == nil
|
||||
nil2 := m2 == nil
|
||||
if nil1 != nil2 || len(m1) != len(m2) {
|
||||
return false
|
||||
}
|
||||
for k, v := range m1 {
|
||||
if v != m2[k] {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// newRequest is a helper function to create a new request with a method and url
|
||||
func newRequest(method, url string) *http.Request {
|
||||
req, err := http.NewRequest(method, url, nil)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return req
|
||||
}
|
714
Godeps/_workspace/src/github.com/gorilla/mux/old_test.go
generated
vendored
714
Godeps/_workspace/src/github.com/gorilla/mux/old_test.go
generated
vendored
@ -1,714 +0,0 @@
|
||||
// Old tests ported to Go1. This is a mess. Want to drop it one day.
|
||||
|
||||
// Copyright 2011 Gorilla Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package mux
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"net/http"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// ResponseRecorder
|
||||
// ----------------------------------------------------------------------------
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// ResponseRecorder is an implementation of http.ResponseWriter that
|
||||
// records its mutations for later inspection in tests.
|
||||
type ResponseRecorder struct {
|
||||
Code int // the HTTP response code from WriteHeader
|
||||
HeaderMap http.Header // the HTTP response headers
|
||||
Body *bytes.Buffer // if non-nil, the bytes.Buffer to append written data to
|
||||
Flushed bool
|
||||
}
|
||||
|
||||
// NewRecorder returns an initialized ResponseRecorder.
|
||||
func NewRecorder() *ResponseRecorder {
|
||||
return &ResponseRecorder{
|
||||
HeaderMap: make(http.Header),
|
||||
Body: new(bytes.Buffer),
|
||||
}
|
||||
}
|
||||
|
||||
// DefaultRemoteAddr is the default remote address to return in RemoteAddr if
|
||||
// an explicit DefaultRemoteAddr isn't set on ResponseRecorder.
|
||||
const DefaultRemoteAddr = "1.2.3.4"
|
||||
|
||||
// Header returns the response headers.
|
||||
func (rw *ResponseRecorder) Header() http.Header {
|
||||
return rw.HeaderMap
|
||||
}
|
||||
|
||||
// Write always succeeds and writes to rw.Body, if not nil.
|
||||
func (rw *ResponseRecorder) Write(buf []byte) (int, error) {
|
||||
if rw.Body != nil {
|
||||
rw.Body.Write(buf)
|
||||
}
|
||||
if rw.Code == 0 {
|
||||
rw.Code = http.StatusOK
|
||||
}
|
||||
return len(buf), nil
|
||||
}
|
||||
|
||||
// WriteHeader sets rw.Code.
|
||||
func (rw *ResponseRecorder) WriteHeader(code int) {
|
||||
rw.Code = code
|
||||
}
|
||||
|
||||
// Flush sets rw.Flushed to true.
|
||||
func (rw *ResponseRecorder) Flush() {
|
||||
rw.Flushed = true
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
func TestRouteMatchers(t *testing.T) {
|
||||
var scheme, host, path, query, method string
|
||||
var headers map[string]string
|
||||
var resultVars map[bool]map[string]string
|
||||
|
||||
router := NewRouter()
|
||||
router.NewRoute().Host("{var1}.google.com").
|
||||
Path("/{var2:[a-z]+}/{var3:[0-9]+}").
|
||||
Queries("foo", "bar").
|
||||
Methods("GET").
|
||||
Schemes("https").
|
||||
Headers("x-requested-with", "XMLHttpRequest")
|
||||
router.NewRoute().Host("www.{var4}.com").
|
||||
PathPrefix("/foo/{var5:[a-z]+}/{var6:[0-9]+}").
|
||||
Queries("baz", "ding").
|
||||
Methods("POST").
|
||||
Schemes("http").
|
||||
Headers("Content-Type", "application/json")
|
||||
|
||||
reset := func() {
|
||||
// Everything match.
|
||||
scheme = "https"
|
||||
host = "www.google.com"
|
||||
path = "/product/42"
|
||||
query = "?foo=bar"
|
||||
method = "GET"
|
||||
headers = map[string]string{"X-Requested-With": "XMLHttpRequest"}
|
||||
resultVars = map[bool]map[string]string{
|
||||
true: {"var1": "www", "var2": "product", "var3": "42"},
|
||||
false: {},
|
||||
}
|
||||
}
|
||||
|
||||
reset2 := func() {
|
||||
// Everything match.
|
||||
scheme = "http"
|
||||
host = "www.google.com"
|
||||
path = "/foo/product/42/path/that/is/ignored"
|
||||
query = "?baz=ding"
|
||||
method = "POST"
|
||||
headers = map[string]string{"Content-Type": "application/json"}
|
||||
resultVars = map[bool]map[string]string{
|
||||
true: {"var4": "google", "var5": "product", "var6": "42"},
|
||||
false: {},
|
||||
}
|
||||
}
|
||||
|
||||
match := func(shouldMatch bool) {
|
||||
url := scheme + "://" + host + path + query
|
||||
request, _ := http.NewRequest(method, url, nil)
|
||||
for key, value := range headers {
|
||||
request.Header.Add(key, value)
|
||||
}
|
||||
|
||||
var routeMatch RouteMatch
|
||||
matched := router.Match(request, &routeMatch)
|
||||
if matched != shouldMatch {
|
||||
// Need better messages. :)
|
||||
if matched {
|
||||
t.Errorf("Should match.")
|
||||
} else {
|
||||
t.Errorf("Should not match.")
|
||||
}
|
||||
}
|
||||
|
||||
if matched {
|
||||
currentRoute := routeMatch.Route
|
||||
if currentRoute == nil {
|
||||
t.Errorf("Expected a current route.")
|
||||
}
|
||||
vars := routeMatch.Vars
|
||||
expectedVars := resultVars[shouldMatch]
|
||||
if len(vars) != len(expectedVars) {
|
||||
t.Errorf("Expected vars: %v Got: %v.", expectedVars, vars)
|
||||
}
|
||||
for name, value := range vars {
|
||||
if expectedVars[name] != value {
|
||||
t.Errorf("Expected vars: %v Got: %v.", expectedVars, vars)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 1st route --------------------------------------------------------------
|
||||
|
||||
// Everything match.
|
||||
reset()
|
||||
match(true)
|
||||
|
||||
// Scheme doesn't match.
|
||||
reset()
|
||||
scheme = "http"
|
||||
match(false)
|
||||
|
||||
// Host doesn't match.
|
||||
reset()
|
||||
host = "www.mygoogle.com"
|
||||
match(false)
|
||||
|
||||
// Path doesn't match.
|
||||
reset()
|
||||
path = "/product/notdigits"
|
||||
match(false)
|
||||
|
||||
// Query doesn't match.
|
||||
reset()
|
||||
query = "?foo=baz"
|
||||
match(false)
|
||||
|
||||
// Method doesn't match.
|
||||
reset()
|
||||
method = "POST"
|
||||
match(false)
|
||||
|
||||
// Header doesn't match.
|
||||
reset()
|
||||
headers = map[string]string{}
|
||||
match(false)
|
||||
|
||||
// Everything match, again.
|
||||
reset()
|
||||
match(true)
|
||||
|
||||
// 2nd route --------------------------------------------------------------
|
||||
|
||||
// Everything match.
|
||||
reset2()
|
||||
match(true)
|
||||
|
||||
// Scheme doesn't match.
|
||||
reset2()
|
||||
scheme = "https"
|
||||
match(false)
|
||||
|
||||
// Host doesn't match.
|
||||
reset2()
|
||||
host = "sub.google.com"
|
||||
match(false)
|
||||
|
||||
// Path doesn't match.
|
||||
reset2()
|
||||
path = "/bar/product/42"
|
||||
match(false)
|
||||
|
||||
// Query doesn't match.
|
||||
reset2()
|
||||
query = "?foo=baz"
|
||||
match(false)
|
||||
|
||||
// Method doesn't match.
|
||||
reset2()
|
||||
method = "GET"
|
||||
match(false)
|
||||
|
||||
// Header doesn't match.
|
||||
reset2()
|
||||
headers = map[string]string{}
|
||||
match(false)
|
||||
|
||||
// Everything match, again.
|
||||
reset2()
|
||||
match(true)
|
||||
}
|
||||
|
||||
type headerMatcherTest struct {
|
||||
matcher headerMatcher
|
||||
headers map[string]string
|
||||
result bool
|
||||
}
|
||||
|
||||
var headerMatcherTests = []headerMatcherTest{
|
||||
{
|
||||
matcher: headerMatcher(map[string]string{"x-requested-with": "XMLHttpRequest"}),
|
||||
headers: map[string]string{"X-Requested-With": "XMLHttpRequest"},
|
||||
result: true,
|
||||
},
|
||||
{
|
||||
matcher: headerMatcher(map[string]string{"x-requested-with": ""}),
|
||||
headers: map[string]string{"X-Requested-With": "anything"},
|
||||
result: true,
|
||||
},
|
||||
{
|
||||
matcher: headerMatcher(map[string]string{"x-requested-with": "XMLHttpRequest"}),
|
||||
headers: map[string]string{},
|
||||
result: false,
|
||||
},
|
||||
}
|
||||
|
||||
type hostMatcherTest struct {
|
||||
matcher *Route
|
||||
url string
|
||||
vars map[string]string
|
||||
result bool
|
||||
}
|
||||
|
||||
var hostMatcherTests = []hostMatcherTest{
|
||||
{
|
||||
matcher: NewRouter().NewRoute().Host("{foo:[a-z][a-z][a-z]}.{bar:[a-z][a-z][a-z]}.{baz:[a-z][a-z][a-z]}"),
|
||||
url: "http://abc.def.ghi/",
|
||||
vars: map[string]string{"foo": "abc", "bar": "def", "baz": "ghi"},
|
||||
result: true,
|
||||
},
|
||||
{
|
||||
matcher: NewRouter().NewRoute().Host("{foo:[a-z][a-z][a-z]}.{bar:[a-z][a-z][a-z]}.{baz:[a-z][a-z][a-z]}"),
|
||||
url: "http://a.b.c/",
|
||||
vars: map[string]string{"foo": "abc", "bar": "def", "baz": "ghi"},
|
||||
result: false,
|
||||
},
|
||||
}
|
||||
|
||||
type methodMatcherTest struct {
|
||||
matcher methodMatcher
|
||||
method string
|
||||
result bool
|
||||
}
|
||||
|
||||
var methodMatcherTests = []methodMatcherTest{
|
||||
{
|
||||
matcher: methodMatcher([]string{"GET", "POST", "PUT"}),
|
||||
method: "GET",
|
||||
result: true,
|
||||
},
|
||||
{
|
||||
matcher: methodMatcher([]string{"GET", "POST", "PUT"}),
|
||||
method: "POST",
|
||||
result: true,
|
||||
},
|
||||
{
|
||||
matcher: methodMatcher([]string{"GET", "POST", "PUT"}),
|
||||
method: "PUT",
|
||||
result: true,
|
||||
},
|
||||
{
|
||||
matcher: methodMatcher([]string{"GET", "POST", "PUT"}),
|
||||
method: "DELETE",
|
||||
result: false,
|
||||
},
|
||||
}
|
||||
|
||||
type pathMatcherTest struct {
|
||||
matcher *Route
|
||||
url string
|
||||
vars map[string]string
|
||||
result bool
|
||||
}
|
||||
|
||||
var pathMatcherTests = []pathMatcherTest{
|
||||
{
|
||||
matcher: NewRouter().NewRoute().Path("/{foo:[0-9][0-9][0-9]}/{bar:[0-9][0-9][0-9]}/{baz:[0-9][0-9][0-9]}"),
|
||||
url: "http://localhost:8080/123/456/789",
|
||||
vars: map[string]string{"foo": "123", "bar": "456", "baz": "789"},
|
||||
result: true,
|
||||
},
|
||||
{
|
||||
matcher: NewRouter().NewRoute().Path("/{foo:[0-9][0-9][0-9]}/{bar:[0-9][0-9][0-9]}/{baz:[0-9][0-9][0-9]}"),
|
||||
url: "http://localhost:8080/1/2/3",
|
||||
vars: map[string]string{"foo": "123", "bar": "456", "baz": "789"},
|
||||
result: false,
|
||||
},
|
||||
}
|
||||
|
||||
type schemeMatcherTest struct {
|
||||
matcher schemeMatcher
|
||||
url string
|
||||
result bool
|
||||
}
|
||||
|
||||
var schemeMatcherTests = []schemeMatcherTest{
|
||||
{
|
||||
matcher: schemeMatcher([]string{"http", "https"}),
|
||||
url: "http://localhost:8080/",
|
||||
result: true,
|
||||
},
|
||||
{
|
||||
matcher: schemeMatcher([]string{"http", "https"}),
|
||||
url: "https://localhost:8080/",
|
||||
result: true,
|
||||
},
|
||||
{
|
||||
matcher: schemeMatcher([]string{"https"}),
|
||||
url: "http://localhost:8080/",
|
||||
result: false,
|
||||
},
|
||||
{
|
||||
matcher: schemeMatcher([]string{"http"}),
|
||||
url: "https://localhost:8080/",
|
||||
result: false,
|
||||
},
|
||||
}
|
||||
|
||||
type urlBuildingTest struct {
|
||||
route *Route
|
||||
vars []string
|
||||
url string
|
||||
}
|
||||
|
||||
var urlBuildingTests = []urlBuildingTest{
|
||||
{
|
||||
route: new(Route).Host("foo.domain.com"),
|
||||
vars: []string{},
|
||||
url: "http://foo.domain.com",
|
||||
},
|
||||
{
|
||||
route: new(Route).Host("{subdomain}.domain.com"),
|
||||
vars: []string{"subdomain", "bar"},
|
||||
url: "http://bar.domain.com",
|
||||
},
|
||||
{
|
||||
route: new(Route).Host("foo.domain.com").Path("/articles"),
|
||||
vars: []string{},
|
||||
url: "http://foo.domain.com/articles",
|
||||
},
|
||||
{
|
||||
route: new(Route).Path("/articles"),
|
||||
vars: []string{},
|
||||
url: "/articles",
|
||||
},
|
||||
{
|
||||
route: new(Route).Path("/articles/{category}/{id:[0-9]+}"),
|
||||
vars: []string{"category", "technology", "id", "42"},
|
||||
url: "/articles/technology/42",
|
||||
},
|
||||
{
|
||||
route: new(Route).Host("{subdomain}.domain.com").Path("/articles/{category}/{id:[0-9]+}"),
|
||||
vars: []string{"subdomain", "foo", "category", "technology", "id", "42"},
|
||||
url: "http://foo.domain.com/articles/technology/42",
|
||||
},
|
||||
}
|
||||
|
||||
func TestHeaderMatcher(t *testing.T) {
|
||||
for _, v := range headerMatcherTests {
|
||||
request, _ := http.NewRequest("GET", "http://localhost:8080/", nil)
|
||||
for key, value := range v.headers {
|
||||
request.Header.Add(key, value)
|
||||
}
|
||||
var routeMatch RouteMatch
|
||||
result := v.matcher.Match(request, &routeMatch)
|
||||
if result != v.result {
|
||||
if v.result {
|
||||
t.Errorf("%#v: should match %v.", v.matcher, request.Header)
|
||||
} else {
|
||||
t.Errorf("%#v: should not match %v.", v.matcher, request.Header)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestHostMatcher(t *testing.T) {
|
||||
for _, v := range hostMatcherTests {
|
||||
request, _ := http.NewRequest("GET", v.url, nil)
|
||||
var routeMatch RouteMatch
|
||||
result := v.matcher.Match(request, &routeMatch)
|
||||
vars := routeMatch.Vars
|
||||
if result != v.result {
|
||||
if v.result {
|
||||
t.Errorf("%#v: should match %v.", v.matcher, v.url)
|
||||
} else {
|
||||
t.Errorf("%#v: should not match %v.", v.matcher, v.url)
|
||||
}
|
||||
}
|
||||
if result {
|
||||
if len(vars) != len(v.vars) {
|
||||
t.Errorf("%#v: vars length should be %v, got %v.", v.matcher, len(v.vars), len(vars))
|
||||
}
|
||||
for name, value := range vars {
|
||||
if v.vars[name] != value {
|
||||
t.Errorf("%#v: expected value %v for key %v, got %v.", v.matcher, v.vars[name], name, value)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if len(vars) != 0 {
|
||||
t.Errorf("%#v: vars length should be 0, got %v.", v.matcher, len(vars))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestMethodMatcher(t *testing.T) {
|
||||
for _, v := range methodMatcherTests {
|
||||
request, _ := http.NewRequest(v.method, "http://localhost:8080/", nil)
|
||||
var routeMatch RouteMatch
|
||||
result := v.matcher.Match(request, &routeMatch)
|
||||
if result != v.result {
|
||||
if v.result {
|
||||
t.Errorf("%#v: should match %v.", v.matcher, v.method)
|
||||
} else {
|
||||
t.Errorf("%#v: should not match %v.", v.matcher, v.method)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestPathMatcher(t *testing.T) {
|
||||
for _, v := range pathMatcherTests {
|
||||
request, _ := http.NewRequest("GET", v.url, nil)
|
||||
var routeMatch RouteMatch
|
||||
result := v.matcher.Match(request, &routeMatch)
|
||||
vars := routeMatch.Vars
|
||||
if result != v.result {
|
||||
if v.result {
|
||||
t.Errorf("%#v: should match %v.", v.matcher, v.url)
|
||||
} else {
|
||||
t.Errorf("%#v: should not match %v.", v.matcher, v.url)
|
||||
}
|
||||
}
|
||||
if result {
|
||||
if len(vars) != len(v.vars) {
|
||||
t.Errorf("%#v: vars length should be %v, got %v.", v.matcher, len(v.vars), len(vars))
|
||||
}
|
||||
for name, value := range vars {
|
||||
if v.vars[name] != value {
|
||||
t.Errorf("%#v: expected value %v for key %v, got %v.", v.matcher, v.vars[name], name, value)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if len(vars) != 0 {
|
||||
t.Errorf("%#v: vars length should be 0, got %v.", v.matcher, len(vars))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestSchemeMatcher(t *testing.T) {
|
||||
for _, v := range schemeMatcherTests {
|
||||
request, _ := http.NewRequest("GET", v.url, nil)
|
||||
var routeMatch RouteMatch
|
||||
result := v.matcher.Match(request, &routeMatch)
|
||||
if result != v.result {
|
||||
if v.result {
|
||||
t.Errorf("%#v: should match %v.", v.matcher, v.url)
|
||||
} else {
|
||||
t.Errorf("%#v: should not match %v.", v.matcher, v.url)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestUrlBuilding(t *testing.T) {
|
||||
|
||||
for _, v := range urlBuildingTests {
|
||||
u, _ := v.route.URL(v.vars...)
|
||||
url := u.String()
|
||||
if url != v.url {
|
||||
t.Errorf("expected %v, got %v", v.url, url)
|
||||
/*
|
||||
reversePath := ""
|
||||
reverseHost := ""
|
||||
if v.route.pathTemplate != nil {
|
||||
reversePath = v.route.pathTemplate.Reverse
|
||||
}
|
||||
if v.route.hostTemplate != nil {
|
||||
reverseHost = v.route.hostTemplate.Reverse
|
||||
}
|
||||
|
||||
t.Errorf("%#v:\nexpected: %q\ngot: %q\nreverse path: %q\nreverse host: %q", v.route, v.url, url, reversePath, reverseHost)
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
ArticleHandler := func(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
router := NewRouter()
|
||||
router.HandleFunc("/articles/{category}/{id:[0-9]+}", ArticleHandler).Name("article")
|
||||
|
||||
url, _ := router.Get("article").URL("category", "technology", "id", "42")
|
||||
expected := "/articles/technology/42"
|
||||
if url.String() != expected {
|
||||
t.Errorf("Expected %v, got %v", expected, url.String())
|
||||
}
|
||||
}
|
||||
|
||||
func TestMatchedRouteName(t *testing.T) {
|
||||
routeName := "stock"
|
||||
router := NewRouter()
|
||||
route := router.NewRoute().Path("/products/").Name(routeName)
|
||||
|
||||
url := "http://www.domain.com/products/"
|
||||
request, _ := http.NewRequest("GET", url, nil)
|
||||
var rv RouteMatch
|
||||
ok := router.Match(request, &rv)
|
||||
|
||||
if !ok || rv.Route != route {
|
||||
t.Errorf("Expected same route, got %+v.", rv.Route)
|
||||
}
|
||||
|
||||
retName := rv.Route.GetName()
|
||||
if retName != routeName {
|
||||
t.Errorf("Expected %q, got %q.", routeName, retName)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSubRouting(t *testing.T) {
|
||||
// Example from docs.
|
||||
router := NewRouter()
|
||||
subrouter := router.NewRoute().Host("www.domain.com").Subrouter()
|
||||
route := subrouter.NewRoute().Path("/products/").Name("products")
|
||||
|
||||
url := "http://www.domain.com/products/"
|
||||
request, _ := http.NewRequest("GET", url, nil)
|
||||
var rv RouteMatch
|
||||
ok := router.Match(request, &rv)
|
||||
|
||||
if !ok || rv.Route != route {
|
||||
t.Errorf("Expected same route, got %+v.", rv.Route)
|
||||
}
|
||||
|
||||
u, _ := router.Get("products").URL()
|
||||
builtUrl := u.String()
|
||||
// Yay, subroute aware of the domain when building!
|
||||
if builtUrl != url {
|
||||
t.Errorf("Expected %q, got %q.", url, builtUrl)
|
||||
}
|
||||
}
|
||||
|
||||
func TestVariableNames(t *testing.T) {
|
||||
route := new(Route).Host("{arg1}.domain.com").Path("/{arg1}/{arg2:[0-9]+}")
|
||||
if route.err == nil {
|
||||
t.Errorf("Expected error for duplicated variable names")
|
||||
}
|
||||
}
|
||||
|
||||
func TestRedirectSlash(t *testing.T) {
|
||||
var route *Route
|
||||
var routeMatch RouteMatch
|
||||
r := NewRouter()
|
||||
|
||||
r.StrictSlash(false)
|
||||
route = r.NewRoute()
|
||||
if route.strictSlash != false {
|
||||
t.Errorf("Expected false redirectSlash.")
|
||||
}
|
||||
|
||||
r.StrictSlash(true)
|
||||
route = r.NewRoute()
|
||||
if route.strictSlash != true {
|
||||
t.Errorf("Expected true redirectSlash.")
|
||||
}
|
||||
|
||||
route = new(Route)
|
||||
route.strictSlash = true
|
||||
route.Path("/{arg1}/{arg2:[0-9]+}/")
|
||||
request, _ := http.NewRequest("GET", "http://localhost/foo/123", nil)
|
||||
routeMatch = RouteMatch{}
|
||||
_ = route.Match(request, &routeMatch)
|
||||
vars := routeMatch.Vars
|
||||
if vars["arg1"] != "foo" {
|
||||
t.Errorf("Expected foo.")
|
||||
}
|
||||
if vars["arg2"] != "123" {
|
||||
t.Errorf("Expected 123.")
|
||||
}
|
||||
rsp := NewRecorder()
|
||||
routeMatch.Handler.ServeHTTP(rsp, request)
|
||||
if rsp.HeaderMap.Get("Location") != "http://localhost/foo/123/" {
|
||||
t.Errorf("Expected redirect header.")
|
||||
}
|
||||
|
||||
route = new(Route)
|
||||
route.strictSlash = true
|
||||
route.Path("/{arg1}/{arg2:[0-9]+}")
|
||||
request, _ = http.NewRequest("GET", "http://localhost/foo/123/", nil)
|
||||
routeMatch = RouteMatch{}
|
||||
_ = route.Match(request, &routeMatch)
|
||||
vars = routeMatch.Vars
|
||||
if vars["arg1"] != "foo" {
|
||||
t.Errorf("Expected foo.")
|
||||
}
|
||||
if vars["arg2"] != "123" {
|
||||
t.Errorf("Expected 123.")
|
||||
}
|
||||
rsp = NewRecorder()
|
||||
routeMatch.Handler.ServeHTTP(rsp, request)
|
||||
if rsp.HeaderMap.Get("Location") != "http://localhost/foo/123" {
|
||||
t.Errorf("Expected redirect header.")
|
||||
}
|
||||
}
|
||||
|
||||
// Test for the new regexp library, still not available in stable Go.
|
||||
func TestNewRegexp(t *testing.T) {
|
||||
var p *routeRegexp
|
||||
var matches []string
|
||||
|
||||
tests := map[string]map[string][]string{
|
||||
"/{foo:a{2}}": {
|
||||
"/a": nil,
|
||||
"/aa": {"aa"},
|
||||
"/aaa": nil,
|
||||
"/aaaa": nil,
|
||||
},
|
||||
"/{foo:a{2,}}": {
|
||||
"/a": nil,
|
||||
"/aa": {"aa"},
|
||||
"/aaa": {"aaa"},
|
||||
"/aaaa": {"aaaa"},
|
||||
},
|
||||
"/{foo:a{2,3}}": {
|
||||
"/a": nil,
|
||||
"/aa": {"aa"},
|
||||
"/aaa": {"aaa"},
|
||||
"/aaaa": nil,
|
||||
},
|
||||
"/{foo:[a-z]{3}}/{bar:[a-z]{2}}": {
|
||||
"/a": nil,
|
||||
"/ab": nil,
|
||||
"/abc": nil,
|
||||
"/abcd": nil,
|
||||
"/abc/ab": {"abc", "ab"},
|
||||
"/abc/abc": nil,
|
||||
"/abcd/ab": nil,
|
||||
},
|
||||
`/{foo:\w{3,}}/{bar:\d{2,}}`: {
|
||||
"/a": nil,
|
||||
"/ab": nil,
|
||||
"/abc": nil,
|
||||
"/abc/1": nil,
|
||||
"/abc/12": {"abc", "12"},
|
||||
"/abcd/12": {"abcd", "12"},
|
||||
"/abcd/123": {"abcd", "123"},
|
||||
},
|
||||
}
|
||||
|
||||
for pattern, paths := range tests {
|
||||
p, _ = newRouteRegexp(pattern, false, false, false, false)
|
||||
for path, result := range paths {
|
||||
matches = p.regexp.FindStringSubmatch(path)
|
||||
if result == nil {
|
||||
if matches != nil {
|
||||
t.Errorf("%v should not match %v.", pattern, path)
|
||||
}
|
||||
} else {
|
||||
if len(matches) != len(result)+1 {
|
||||
t.Errorf("Expected %v matches, got %v.", len(result)+1, len(matches))
|
||||
} else {
|
||||
for k, v := range result {
|
||||
if matches[k+1] != v {
|
||||
t.Errorf("Expected %v, got %v.", v, matches[k+1])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
117
Godeps/_workspace/src/github.com/gorilla/rpc/v2/json/json_test.go
generated
vendored
117
Godeps/_workspace/src/github.com/gorilla/rpc/v2/json/json_test.go
generated
vendored
@ -1,117 +0,0 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Copyright 2012 The Gorilla Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package json
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/gorilla/rpc/v2"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrResponseError = errors.New("response error")
|
||||
ErrResponseJsonError = &Error{Data: map[string]interface{}{
|
||||
"stackstrace": map[string]interface{}{"0": "foo()"},
|
||||
"error": "a message",
|
||||
}}
|
||||
)
|
||||
|
||||
type Service1Request struct {
|
||||
A int
|
||||
B int
|
||||
}
|
||||
|
||||
type Service1Response struct {
|
||||
Result int
|
||||
}
|
||||
|
||||
type Service1 struct {
|
||||
}
|
||||
|
||||
func (t *Service1) Multiply(r *http.Request, req *Service1Request, res *Service1Response) error {
|
||||
res.Result = req.A * req.B
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *Service1) ResponseError(r *http.Request, req *Service1Request, res *Service1Response) error {
|
||||
return ErrResponseError
|
||||
}
|
||||
|
||||
func (t *Service1) ResponseJsonError(r *http.Request, req *Service1Request, res *Service1Response) error {
|
||||
return ErrResponseJsonError
|
||||
}
|
||||
|
||||
func execute(t *testing.T, s *rpc.Server, method string, req, res interface{}) error {
|
||||
if !s.HasMethod(method) {
|
||||
t.Fatal("Expected to be registered:", method)
|
||||
}
|
||||
|
||||
buf, _ := EncodeClientRequest(method, req)
|
||||
body := bytes.NewBuffer(buf)
|
||||
r, _ := http.NewRequest("POST", "http://localhost:8080/", body)
|
||||
r.Header.Set("Content-Type", "application/json")
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
s.ServeHTTP(w, r)
|
||||
|
||||
return DecodeClientResponse(w.Body, res)
|
||||
}
|
||||
|
||||
func executeRaw(t *testing.T, s *rpc.Server, req json.RawMessage) (int, *bytes.Buffer) {
|
||||
r, _ := http.NewRequest("POST", "http://localhost:8080/", bytes.NewBuffer(req))
|
||||
r.Header.Set("Content-Type", "application/json")
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
s.ServeHTTP(w, r)
|
||||
|
||||
return w.Code, w.Body
|
||||
}
|
||||
|
||||
func field(name string, blob json.RawMessage) (v interface{}, ok bool) {
|
||||
var obj map[string]interface{}
|
||||
if err := json.Unmarshal(blob, &obj); err != nil {
|
||||
return nil, false
|
||||
}
|
||||
v, ok = obj[name]
|
||||
return
|
||||
}
|
||||
|
||||
func TestService(t *testing.T) {
|
||||
s := rpc.NewServer()
|
||||
s.RegisterCodec(NewCodec(), "application/json")
|
||||
s.RegisterService(new(Service1), "")
|
||||
|
||||
var res Service1Response
|
||||
if err := execute(t, s, "Service1.Multiply", &Service1Request{4, 2}, &res); err != nil {
|
||||
t.Error("Expected err to be nil, but got", err)
|
||||
}
|
||||
if res.Result != 8 {
|
||||
t.Error("Expected res.Result to be 8, but got", res.Result)
|
||||
}
|
||||
if err := execute(t, s, "Service1.ResponseError", &Service1Request{4, 2}, &res); err == nil {
|
||||
t.Errorf("Expected to get %q, but got nil", ErrResponseError)
|
||||
} else if err.Error() != ErrResponseError.Error() {
|
||||
t.Errorf("Expected to get %q, but got %q", ErrResponseError, err)
|
||||
}
|
||||
if code, res := executeRaw(t, s, json.RawMessage(`{"method":"Service1.Multiply","params":null,"id":5}`)); code != 400 {
|
||||
t.Error("Expected response code to be 400, but got", code)
|
||||
} else if v, ok := field("result", res.Bytes()); !ok || v != nil {
|
||||
t.Errorf("Expected ok to be true and v to be nil, but got %v and %v", ok, v)
|
||||
}
|
||||
if err := execute(t, s, "Service1.ResponseJsonError", &Service1Request{4, 2}, &res); err == nil {
|
||||
t.Errorf("Expected to get %q, but got nil", ErrResponseError)
|
||||
} else if jsonErr, ok := err.(*Error); !ok {
|
||||
t.Error("Expected err to be of a *json.Error type")
|
||||
} else if !reflect.DeepEqual(jsonErr.Data, ErrResponseJsonError.Data) {
|
||||
t.Errorf("Expected jsonErr to be %q, but got %q", ErrResponseJsonError, jsonErr)
|
||||
}
|
||||
}
|
75
Godeps/_workspace/src/github.com/gorilla/rpc/v2/json2/client.go
generated
vendored
75
Godeps/_workspace/src/github.com/gorilla/rpc/v2/json2/client.go
generated
vendored
@ -1,75 +0,0 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Copyright 2012 The Gorilla Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package json2
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
"math/rand"
|
||||
)
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Request and Response
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// clientRequest represents a JSON-RPC request sent by a client.
|
||||
type clientRequest struct {
|
||||
// JSON-RPC protocol.
|
||||
Version string `json:"jsonrpc"`
|
||||
|
||||
// A String containing the name of the method to be invoked.
|
||||
Method string `json:"method"`
|
||||
|
||||
// Object to pass as request parameter to the method.
|
||||
Params interface{} `json:"params"`
|
||||
|
||||
// The request id. This can be of any type. It is used to match the
|
||||
// response with the request that it is replying to.
|
||||
Id uint64 `json:"id"`
|
||||
}
|
||||
|
||||
// clientResponse represents a JSON-RPC response returned to a client.
|
||||
type clientResponse struct {
|
||||
Version string `json:"jsonrpc"`
|
||||
Result *json.RawMessage `json:"result"`
|
||||
Error *json.RawMessage `json:"error"`
|
||||
}
|
||||
|
||||
// EncodeClientRequest encodes parameters for a JSON-RPC client request.
|
||||
func EncodeClientRequest(method string, args interface{}) ([]byte, error) {
|
||||
c := &clientRequest{
|
||||
Version: "2.0",
|
||||
Method: method,
|
||||
Params: args,
|
||||
Id: uint64(rand.Int63()),
|
||||
}
|
||||
return json.Marshal(c)
|
||||
}
|
||||
|
||||
// DecodeClientResponse decodes the response body of a client request into
|
||||
// the interface reply.
|
||||
func DecodeClientResponse(r io.Reader, reply interface{}) error {
|
||||
var c clientResponse
|
||||
if err := json.NewDecoder(r).Decode(&c); err != nil {
|
||||
return err
|
||||
}
|
||||
if c.Error != nil {
|
||||
jsonErr := &Error{}
|
||||
if err := json.Unmarshal(*c.Error, jsonErr); err != nil {
|
||||
return &Error{
|
||||
Code: E_SERVER,
|
||||
Message: string(*c.Error),
|
||||
}
|
||||
}
|
||||
return jsonErr
|
||||
}
|
||||
|
||||
if c.Result == nil {
|
||||
return ErrNullResult
|
||||
}
|
||||
|
||||
return json.Unmarshal(*c.Result, reply)
|
||||
}
|
39
Godeps/_workspace/src/github.com/gorilla/rpc/v2/json2/error.go
generated
vendored
39
Godeps/_workspace/src/github.com/gorilla/rpc/v2/json2/error.go
generated
vendored
@ -1,39 +0,0 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Copyright 2012 The Gorilla Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package json2
|
||||
|
||||
import (
|
||||
"errors"
|
||||
)
|
||||
|
||||
type ErrorCode int
|
||||
|
||||
const (
|
||||
E_PARSE ErrorCode = -32700
|
||||
E_INVALID_REQ ErrorCode = -32600
|
||||
E_NO_METHOD ErrorCode = -32601
|
||||
E_BAD_PARAMS ErrorCode = -32602
|
||||
E_INTERNAL ErrorCode = -32603
|
||||
E_SERVER ErrorCode = -32000
|
||||
)
|
||||
|
||||
var ErrNullResult = errors.New("result is null")
|
||||
|
||||
type Error struct {
|
||||
// A Number that indicates the error type that occurred.
|
||||
Code ErrorCode `json:"code"` /* required */
|
||||
|
||||
// A String providing a short description of the error.
|
||||
// The message SHOULD be limited to a concise single sentence.
|
||||
Message string `json:"message"` /* required */
|
||||
|
||||
// A Primitive or Structured value that contains additional information about the error.
|
||||
Data interface{} `json:"data"` /* optional */
|
||||
}
|
||||
|
||||
func (e *Error) Error() string {
|
||||
return e.Message
|
||||
}
|
161
Godeps/_workspace/src/github.com/gorilla/rpc/v2/json2/json_test.go
generated
vendored
161
Godeps/_workspace/src/github.com/gorilla/rpc/v2/json2/json_test.go
generated
vendored
@ -1,161 +0,0 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Copyright 2012 The Gorilla Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package json2
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
"github.com/gorilla/rpc/v2"
|
||||
)
|
||||
|
||||
// ResponseRecorder is an implementation of http.ResponseWriter that
|
||||
// records its mutations for later inspection in tests.
|
||||
type ResponseRecorder struct {
|
||||
Code int // the HTTP response code from WriteHeader
|
||||
HeaderMap http.Header // the HTTP response headers
|
||||
Body *bytes.Buffer // if non-nil, the bytes.Buffer to append written data to
|
||||
Flushed bool
|
||||
}
|
||||
|
||||
// NewRecorder returns an initialized ResponseRecorder.
|
||||
func NewRecorder() *ResponseRecorder {
|
||||
return &ResponseRecorder{
|
||||
HeaderMap: make(http.Header),
|
||||
Body: new(bytes.Buffer),
|
||||
}
|
||||
}
|
||||
|
||||
// DefaultRemoteAddr is the default remote address to return in RemoteAddr if
|
||||
// an explicit DefaultRemoteAddr isn't set on ResponseRecorder.
|
||||
const DefaultRemoteAddr = "1.2.3.4"
|
||||
|
||||
// Header returns the response headers.
|
||||
func (rw *ResponseRecorder) Header() http.Header {
|
||||
return rw.HeaderMap
|
||||
}
|
||||
|
||||
// Write always succeeds and writes to rw.Body, if not nil.
|
||||
func (rw *ResponseRecorder) Write(buf []byte) (int, error) {
|
||||
if rw.Body != nil {
|
||||
rw.Body.Write(buf)
|
||||
}
|
||||
if rw.Code == 0 {
|
||||
rw.Code = http.StatusOK
|
||||
}
|
||||
return len(buf), nil
|
||||
}
|
||||
|
||||
// WriteHeader sets rw.Code.
|
||||
func (rw *ResponseRecorder) WriteHeader(code int) {
|
||||
rw.Code = code
|
||||
}
|
||||
|
||||
// Flush sets rw.Flushed to true.
|
||||
func (rw *ResponseRecorder) Flush() {
|
||||
rw.Flushed = true
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
var ErrResponseError = errors.New("response error")
|
||||
|
||||
type Service1Request struct {
|
||||
A int
|
||||
B int
|
||||
}
|
||||
|
||||
type Service1BadRequest struct {
|
||||
V string `json:"jsonrpc"`
|
||||
M string `json:"method"`
|
||||
ID uint64 `json:"id"`
|
||||
}
|
||||
|
||||
type Service1Response struct {
|
||||
Result int
|
||||
}
|
||||
|
||||
type Service1 struct {
|
||||
}
|
||||
|
||||
func (t *Service1) Multiply(r *http.Request, req *Service1Request, res *Service1Response) error {
|
||||
res.Result = req.A * req.B
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *Service1) ResponseError(r *http.Request, req *Service1Request, res *Service1Response) error {
|
||||
return ErrResponseError
|
||||
}
|
||||
|
||||
func execute(t *testing.T, s *rpc.Server, method string, req, res interface{}) error {
|
||||
if !s.HasMethod(method) {
|
||||
t.Fatal("Expected to be registered:", method)
|
||||
}
|
||||
|
||||
buf, _ := EncodeClientRequest(method, req)
|
||||
body := bytes.NewBuffer(buf)
|
||||
r, _ := http.NewRequest("POST", "http://localhost:8080/", body)
|
||||
r.Header.Set("Content-Type", "application/json")
|
||||
|
||||
w := NewRecorder()
|
||||
s.ServeHTTP(w, r)
|
||||
|
||||
return DecodeClientResponse(w.Body, res)
|
||||
}
|
||||
|
||||
func executeRaw(t *testing.T, s *rpc.Server, req interface{}, res interface{}) error {
|
||||
j, _ := json.Marshal(req)
|
||||
r, _ := http.NewRequest("POST", "http://localhost:8080/", bytes.NewBuffer(j))
|
||||
r.Header.Set("Content-Type", "application/json")
|
||||
|
||||
w := NewRecorder()
|
||||
s.ServeHTTP(w, r)
|
||||
|
||||
return DecodeClientResponse(w.Body, res)
|
||||
}
|
||||
|
||||
func TestService(t *testing.T) {
|
||||
s := rpc.NewServer()
|
||||
s.RegisterCodec(NewCodec(), "application/json")
|
||||
s.RegisterService(new(Service1), "")
|
||||
|
||||
var res Service1Response
|
||||
if err := execute(t, s, "Service1.Multiply", &Service1Request{4, 2}, &res); err != nil {
|
||||
t.Error("Expected err to be nil, but got:", err)
|
||||
}
|
||||
if res.Result != 8 {
|
||||
t.Errorf("Wrong response: %v.", res.Result)
|
||||
}
|
||||
|
||||
if err := execute(t, s, "Service1.ResponseError", &Service1Request{4, 2}, &res); err == nil {
|
||||
t.Errorf("Expected to get %q, but got nil", ErrResponseError)
|
||||
} else if err.Error() != ErrResponseError.Error() {
|
||||
t.Errorf("Expected to get %q, but got %q", ErrResponseError, err)
|
||||
}
|
||||
|
||||
if err := executeRaw(t, s, &Service1BadRequest{"2.0", "Service1.Multiply", 1}, &res); err == nil {
|
||||
t.Errorf("Expected error but error in nil")
|
||||
}
|
||||
}
|
||||
|
||||
func TestDecodeNullResult(t *testing.T) {
|
||||
data := `{"jsonrpc": "2.0", "id": 12345, "result": null}`
|
||||
reader := bytes.NewReader([]byte(data))
|
||||
var result interface{}
|
||||
|
||||
err := DecodeClientResponse(reader, &result)
|
||||
|
||||
if err != ErrNullResult {
|
||||
t.Error("Expected err no be ErrNullResult, but got:", err)
|
||||
}
|
||||
|
||||
if result != nil {
|
||||
t.Error("Expected result to be nil, but got:", result)
|
||||
}
|
||||
}
|
190
Godeps/_workspace/src/github.com/gorilla/rpc/v2/json2/server.go
generated
vendored
190
Godeps/_workspace/src/github.com/gorilla/rpc/v2/json2/server.go
generated
vendored
@ -1,190 +0,0 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Copyright 2012 The Gorilla Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package json2
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
|
||||
"github.com/gorilla/rpc/v2"
|
||||
)
|
||||
|
||||
var null = json.RawMessage([]byte("null"))
|
||||
var Version = "2.0"
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Request and Response
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// serverRequest represents a JSON-RPC request received by the server.
|
||||
type serverRequest struct {
|
||||
// JSON-RPC protocol.
|
||||
Version string `json:"jsonrpc"`
|
||||
|
||||
// A String containing the name of the method to be invoked.
|
||||
Method string `json:"method"`
|
||||
|
||||
// A Structured value to pass as arguments to the method.
|
||||
Params *json.RawMessage `json:"params"`
|
||||
|
||||
// The request id. MUST be a string, number or null.
|
||||
// Our implementation will not do type checking for id.
|
||||
// It will be copied as it is.
|
||||
Id *json.RawMessage `json:"id"`
|
||||
}
|
||||
|
||||
// serverResponse represents a JSON-RPC response returned by the server.
|
||||
type serverResponse struct {
|
||||
// JSON-RPC protocol.
|
||||
Version string `json:"jsonrpc"`
|
||||
|
||||
// The Object that was returned by the invoked method. This must be null
|
||||
// in case there was an error invoking the method.
|
||||
// As per spec the member will be omitted if there was an error.
|
||||
Result interface{} `json:"result,omitempty"`
|
||||
|
||||
// An Error object if there was an error invoking the method. It must be
|
||||
// null if there was no error.
|
||||
// As per spec the member will be omitted if there was no error.
|
||||
Error *Error `json:"error,omitempty"`
|
||||
|
||||
// This must be the same id as the request it is responding to.
|
||||
Id *json.RawMessage `json:"id"`
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Codec
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// NewcustomCodec returns a new JSON Codec based on passed encoder selector.
|
||||
func NewCustomCodec(encSel rpc.EncoderSelector) *Codec {
|
||||
return &Codec{encSel: encSel}
|
||||
}
|
||||
|
||||
// NewCodec returns a new JSON Codec.
|
||||
func NewCodec() *Codec {
|
||||
return NewCustomCodec(rpc.DefaultEncoderSelector)
|
||||
}
|
||||
|
||||
// Codec creates a CodecRequest to process each request.
|
||||
type Codec struct {
|
||||
encSel rpc.EncoderSelector
|
||||
}
|
||||
|
||||
// NewRequest returns a CodecRequest.
|
||||
func (c *Codec) NewRequest(r *http.Request) rpc.CodecRequest {
|
||||
return newCodecRequest(r, c.encSel.Select(r))
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// CodecRequest
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// newCodecRequest returns a new CodecRequest.
|
||||
func newCodecRequest(r *http.Request, encoder rpc.Encoder) rpc.CodecRequest {
|
||||
// Decode the request body and check if RPC method is valid.
|
||||
req := new(serverRequest)
|
||||
err := json.NewDecoder(r.Body).Decode(req)
|
||||
if err != nil {
|
||||
err = &Error{
|
||||
Code: E_PARSE,
|
||||
Message: err.Error(),
|
||||
Data: req,
|
||||
}
|
||||
}
|
||||
if req.Version != Version {
|
||||
err = &Error{
|
||||
Code: E_INVALID_REQ,
|
||||
Message: "jsonrpc must be " + Version,
|
||||
Data: req,
|
||||
}
|
||||
}
|
||||
r.Body.Close()
|
||||
return &CodecRequest{request: req, err: err, encoder: encoder}
|
||||
}
|
||||
|
||||
// CodecRequest decodes and encodes a single request.
|
||||
type CodecRequest struct {
|
||||
request *serverRequest
|
||||
err error
|
||||
encoder rpc.Encoder
|
||||
}
|
||||
|
||||
// Method returns the RPC method for the current request.
|
||||
//
|
||||
// The method uses a dotted notation as in "Service.Method".
|
||||
func (c *CodecRequest) Method() (string, error) {
|
||||
if c.err == nil {
|
||||
return c.request.Method, nil
|
||||
}
|
||||
return "", c.err
|
||||
}
|
||||
|
||||
// ReadRe<quest fills the request object for the RPC method.
|
||||
func (c *CodecRequest) ReadRequest(args interface{}) error {
|
||||
if c.err == nil {
|
||||
if c.request.Params != nil {
|
||||
// JSON params structured object. Unmarshal to the args object.
|
||||
err := json.Unmarshal(*c.request.Params, args)
|
||||
if err != nil {
|
||||
c.err = &Error{
|
||||
Code: E_INVALID_REQ,
|
||||
Message: err.Error(),
|
||||
Data: c.request.Params,
|
||||
}
|
||||
}
|
||||
} else {
|
||||
c.err = &Error{
|
||||
Code: E_INVALID_REQ,
|
||||
Message: "rpc: method request ill-formed: missing params field",
|
||||
}
|
||||
}
|
||||
}
|
||||
return c.err
|
||||
}
|
||||
|
||||
// WriteResponse encodes the response and writes it to the ResponseWriter.
|
||||
func (c *CodecRequest) WriteResponse(w http.ResponseWriter, reply interface{}) {
|
||||
res := &serverResponse{
|
||||
Version: Version,
|
||||
Result: reply,
|
||||
Id: c.request.Id,
|
||||
}
|
||||
c.writeServerResponse(w, res)
|
||||
}
|
||||
|
||||
func (c *CodecRequest) WriteError(w http.ResponseWriter, status int, err error) {
|
||||
jsonErr, ok := err.(*Error)
|
||||
if !ok {
|
||||
jsonErr = &Error{
|
||||
Code: E_SERVER,
|
||||
Message: err.Error(),
|
||||
}
|
||||
}
|
||||
res := &serverResponse{
|
||||
Version: Version,
|
||||
Error: jsonErr,
|
||||
Id: c.request.Id,
|
||||
}
|
||||
c.writeServerResponse(w, res)
|
||||
}
|
||||
|
||||
func (c *CodecRequest) writeServerResponse(w http.ResponseWriter, res *serverResponse) {
|
||||
// Id is null for notifications and they don't have a response.
|
||||
if c.request.Id != nil {
|
||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||
encoder := json.NewEncoder(c.encoder.Encode(w))
|
||||
err := encoder.Encode(res)
|
||||
|
||||
// Not sure in which case will this happen. But seems harmless.
|
||||
if err != nil {
|
||||
rpc.WriteError(w, 400, err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type EmptyResponse struct {
|
||||
}
|
10
Godeps/_workspace/src/github.com/gorilla/rpc/v2/json2/testapp/README.md
generated
vendored
10
Godeps/_workspace/src/github.com/gorilla/rpc/v2/json2/testapp/README.md
generated
vendored
@ -1,10 +0,0 @@
|
||||
Counter (TestApp)
|
||||
=================
|
||||
|
||||
1) Build
|
||||
|
||||
$ go build counter.go
|
||||
$ ./counter
|
||||
|
||||
|
||||
2) Navigate to localhost:65534 on the browser to access the app.
|
50
Godeps/_workspace/src/github.com/gorilla/rpc/v2/json2/testapp/counter.go
generated
vendored
50
Godeps/_workspace/src/github.com/gorilla/rpc/v2/json2/testapp/counter.go
generated
vendored
@ -1,50 +0,0 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Copyright 2013 The Gorilla Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"log"
|
||||
"net/http"
|
||||
|
||||
"github.com/gorilla/rpc/v2"
|
||||
"github.com/gorilla/rpc/v2/json2"
|
||||
)
|
||||
|
||||
type Counter struct {
|
||||
Count int
|
||||
}
|
||||
|
||||
type IncrReq struct {
|
||||
Delta int
|
||||
}
|
||||
|
||||
// Notification.
|
||||
func (c *Counter) Incr(r *http.Request, req *IncrReq, res *json2.EmptyResponse) error {
|
||||
log.Printf("<- Incr %+v", *req)
|
||||
c.Count += req.Delta
|
||||
return nil
|
||||
}
|
||||
|
||||
type GetReq struct {
|
||||
}
|
||||
|
||||
func (c *Counter) Get(r *http.Request, req *GetReq, res *Counter) error {
|
||||
log.Printf("<- Get %+v", *req)
|
||||
*res = *c
|
||||
log.Printf("-> %v", *res)
|
||||
return nil
|
||||
}
|
||||
|
||||
func main() {
|
||||
address := flag.String("address", ":65534", "")
|
||||
s := rpc.NewServer()
|
||||
s.RegisterCodec(json2.NewCustomCodec(&rpc.CompressionSelector{}), "application/json")
|
||||
s.RegisterService(new(Counter), "")
|
||||
http.Handle("/", http.StripPrefix("/", http.FileServer(http.Dir("./"))))
|
||||
http.Handle("/jsonrpc/", s)
|
||||
log.Fatal(http.ListenAndServe(*address, nil))
|
||||
}
|
64
Godeps/_workspace/src/github.com/gorilla/rpc/v2/json2/testapp/counter.js
generated
vendored
64
Godeps/_workspace/src/github.com/gorilla/rpc/v2/json2/testapp/counter.js
generated
vendored
@ -1,64 +0,0 @@
|
||||
function log(m, label) {
|
||||
msg = $("<li><span>" + m + "</span></li>");
|
||||
msg.find("span").addClass(label);
|
||||
out = $("#output");
|
||||
out.append(msg);
|
||||
out.animate({"scrollTop": out[0].scrollHeight}, "fast");
|
||||
}
|
||||
|
||||
$(document).ready(function() {
|
||||
$("#incr").click(function() {
|
||||
req = {
|
||||
method : "Counter.Incr",
|
||||
params : {delta: 1},
|
||||
};
|
||||
log("<- " + JSON.stringify(req), "secondary label");
|
||||
$.jsonrpc(req);
|
||||
});
|
||||
$("#get").click(function() {
|
||||
req = {
|
||||
method : "Counter.Get",
|
||||
params : {},
|
||||
};
|
||||
log("<- " + JSON.stringify(req), "label");
|
||||
$.jsonrpc(req, {
|
||||
success : function(result) {
|
||||
$("#get").addClass("success");
|
||||
setTimeout(function() {
|
||||
$("#get").removeClass("success");
|
||||
}, 2000);
|
||||
log("-> " + JSON.stringify(result), "success label");
|
||||
},
|
||||
error : function(error) {
|
||||
$("#get").addClass("alert");
|
||||
setTimeout(function() {
|
||||
$("#get").removeClass("alert");
|
||||
}, 2000);
|
||||
log("-> " + JSON.stringify(error), "alert label");
|
||||
},
|
||||
});
|
||||
});
|
||||
$("#nan").click(function() {
|
||||
req = {
|
||||
method : "Counter.Nan",
|
||||
params : {},
|
||||
};
|
||||
log("<- " + JSON.stringify(req), "label");
|
||||
$.jsonrpc(req, {
|
||||
success : function(result) {
|
||||
$("#nan").addClass("success");
|
||||
setTimeout(function() {
|
||||
$("#nan").removeClass("success");
|
||||
}, 2000);
|
||||
log("-> " + JSON.stringify(result), "success label");
|
||||
},
|
||||
error : function(error) {
|
||||
$("#nan").addClass("alert");
|
||||
setTimeout(function() {
|
||||
$("#nan").removeClass("alert");
|
||||
}, 2000);
|
||||
log("-> " + JSON.stringify(error), "alert label");
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
32
Godeps/_workspace/src/github.com/gorilla/rpc/v2/json2/testapp/index.html
generated
vendored
32
Godeps/_workspace/src/github.com/gorilla/rpc/v2/json2/testapp/index.html
generated
vendored
@ -1,32 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<script src="//code.jquery.com/jquery-1.9.1.js"></script>
|
||||
<link href="//cdn.jsdelivr.net/foundation/4.1.2/css/foundation.min.css" rel='stylesheet' type='text/css'>
|
||||
<link href="//fonts.googleapis.com/css?family=Inconsolata" rel='stylesheet' type='text/css'>
|
||||
<script src="jquery.jsonrpc.js"></script>
|
||||
<script src="counter.js"></script>
|
||||
<title>Counter</title>
|
||||
<style>
|
||||
body {
|
||||
font-family: 'Inconsolata', sans-serif;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body style="padding:20px">
|
||||
<div class="row">
|
||||
<div class="large-1 columns"><a id="incr" href="#" class="small secondary button">Incr</a></div>
|
||||
<div class="large-1 columns"><a id="get" href="#" class="small button">Get </a></div>
|
||||
<div class="large-1 columns"><a id="nan" href="#" class="small button">Nan </a></div>
|
||||
<div class="large-9 columns"></div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="large-12 columns panel">
|
||||
<ul id="output" style="height:600px;overflow:scroll;list-style-type:none;">
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
158
Godeps/_workspace/src/github.com/gorilla/rpc/v2/json2/testapp/jquery.jsonrpc.js
generated
vendored
158
Godeps/_workspace/src/github.com/gorilla/rpc/v2/json2/testapp/jquery.jsonrpc.js
generated
vendored
@ -1,158 +0,0 @@
|
||||
/*
|
||||
* jQuery JSON-RPC Plugin
|
||||
*
|
||||
* @version: 0.3(2012-05-17)
|
||||
* @author hagino3000 <http://twitter.com/hagino3000> (Takashi Nishibayashi)
|
||||
* @author alanjds <http://twitter.com/alanjds> (Alan Justino da Silva)
|
||||
*
|
||||
* A JSON-RPC 2.0 implementation for jQuery.
|
||||
* JSON-RPC is a stateless, light-weight remote procedure call (RPC) protocol.
|
||||
* Read more in the <http://groups.google.com/group/json-rpc/web/json-rpc-2-0>
|
||||
*
|
||||
* Requires json2.js<http://www.json.org/json2.js> if browser has not window.JSON.
|
||||
*
|
||||
* Usage:
|
||||
* $.jsonrpc(data [, callbacks [, debug]]);
|
||||
*
|
||||
* where data = {url: '/rpc/', method:'simplefunc', params:['posi', 'tional']}
|
||||
* or data = {url: '/rpc/', method:'complexfunc', params:{nam:'ed', par:'ams'}}
|
||||
* and callbacks = {success: successFunc, error: errorFunc}
|
||||
*
|
||||
* Setting no callback produces a JSON-RPC Notification.
|
||||
* 'data' accepts 'timeout' keyword too, who sets the $.ajax request timeout.
|
||||
* Setting 'debug' to true prints responses to Firebug's console.info
|
||||
*
|
||||
* Examples:
|
||||
* // A RPC call with named parameters
|
||||
* $.jsonrpc({
|
||||
* url : '/rpc',
|
||||
* method : 'createUser',
|
||||
* params : {name : 'John Smith', userId : '1000'}
|
||||
* }, {
|
||||
* success : function(result) {
|
||||
* //doSomething
|
||||
* },
|
||||
* error : function(error) {
|
||||
* //doSomething
|
||||
* }
|
||||
* });
|
||||
*
|
||||
* // Once set defaultUrl, url option is no need
|
||||
* $.jsonrpc.defaultUrl = '/rpc';
|
||||
*
|
||||
* // A Notification
|
||||
* $.jsonrpc({
|
||||
* method : 'notify',
|
||||
* params : {action : 'logout', userId : '1000'}
|
||||
* });
|
||||
*
|
||||
* // A Notification using console to debug and with timeout set
|
||||
* $.jsonrpc({
|
||||
* method : 'notify',
|
||||
* params : {action : 'logout', userId : '1000'},
|
||||
* debug : true,
|
||||
* timeout : 500,
|
||||
* });
|
||||
*
|
||||
* // Set DataFilter. It is useful for buggy API that returns sometimes not json but html (when 500, 403..).
|
||||
* $.jsonrpc({
|
||||
* method : 'getUser',
|
||||
* dataFilter : function(data, type) {
|
||||
* try {
|
||||
* return JSON.parse(data);
|
||||
* } catch(e) {
|
||||
* return {error : {message : 'Cannot parse response', data : data}};
|
||||
* }
|
||||
* }, function(result){ doSomething... }
|
||||
* }, {
|
||||
* success : handleSuccess
|
||||
* error : handleFailure
|
||||
* });
|
||||
*
|
||||
* This document is licensed as free software under the terms of the
|
||||
* MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
(function($) {
|
||||
|
||||
var rpcid = 1,
|
||||
emptyFn = function() {};
|
||||
|
||||
$.jsonrpc = $.jsonrpc || function(data, callbacks, debug) {
|
||||
debug = debug || false;
|
||||
|
||||
var postdata = {
|
||||
jsonrpc: '2.0',
|
||||
method: data.method || '',
|
||||
params: data.params || {}
|
||||
};
|
||||
if (callbacks) {
|
||||
postdata.id = data.id || rpcid++;
|
||||
} else {
|
||||
callbacks = emptyFn;
|
||||
}
|
||||
|
||||
if (typeof(callbacks) === 'function') {
|
||||
callbacks = {
|
||||
success: callbacks,
|
||||
error: callbacks
|
||||
};
|
||||
}
|
||||
|
||||
var dataFilter = data.dataFilter;
|
||||
|
||||
var ajaxopts = {
|
||||
url: data.url || $.jsonrpc.defaultUrl,
|
||||
contentType: 'application/json',
|
||||
dataType: 'text',
|
||||
dataFilter: function(data, type) {
|
||||
if (dataFilter) {
|
||||
return dataFilter(data);
|
||||
} else {
|
||||
if (data != "") return JSON.parse(data);
|
||||
}
|
||||
},
|
||||
type: 'POST',
|
||||
processData: false,
|
||||
data: JSON.stringify(postdata),
|
||||
success: function(resp) {
|
||||
if (resp && !resp.error) {
|
||||
return callbacks.success && callbacks.success(resp.result);
|
||||
} else if (resp && resp.error) {
|
||||
return callbacks.error && callbacks.error(resp.error);
|
||||
} else {
|
||||
return callbacks.error && callbacks.error(resp);
|
||||
}
|
||||
},
|
||||
error: function(xhr, status, error) {
|
||||
if (error === 'timeout') {
|
||||
callbacks.error({
|
||||
status: status,
|
||||
code: 0,
|
||||
message: 'Request Timeout'
|
||||
});
|
||||
return;
|
||||
}
|
||||
// If response code is 404, 400, 500, server returns error object
|
||||
try {
|
||||
var res = JSON.parse(xhr.responseText);
|
||||
callbacks.error(res.error);
|
||||
} catch (e) {
|
||||
callbacks.error({
|
||||
status: status,
|
||||
code: 0,
|
||||
message: error
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
if (data.timeout) {
|
||||
ajaxopts['timeout'] = data.timeout;
|
||||
}
|
||||
|
||||
$.ajax(ajaxopts);
|
||||
|
||||
return $;
|
||||
}
|
||||
$.jsonrpc.defaultUrl = $.jsonrpc.defaultUrl || '/jsonrpc/';
|
||||
|
||||
})(jQuery);
|
48
Godeps/_workspace/src/github.com/gorilla/rpc/v2/protorpc/doc.go
generated
vendored
48
Godeps/_workspace/src/github.com/gorilla/rpc/v2/protorpc/doc.go
generated
vendored
@ -1,48 +0,0 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Copyright 2012 The Gorilla Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
/*
|
||||
Package gorilla/rpc/protorpc provides a codec for ProtoRPC over HTTP services.
|
||||
|
||||
To register the codec in a RPC server:
|
||||
|
||||
import (
|
||||
"http"
|
||||
"github.com/gorilla/rpc/v2"
|
||||
"github.com/gorilla/rpc/v2/protorpc"
|
||||
)
|
||||
|
||||
func init() {
|
||||
s := rpc.NewServer()
|
||||
s.RegisterCodec(protorpc.NewCodec(), "application/json")
|
||||
// [...]
|
||||
http.Handle("/rpc", s)
|
||||
}
|
||||
|
||||
A codec is tied to a content type. In the example above, the server
|
||||
will use the ProtoRPC codec for requests with "application/json" as
|
||||
the value for the "Content-Type" header.
|
||||
|
||||
This package implement ProtoRPC, based on the JSON-RPC transport, it
|
||||
differs in that it uses HTTP as its envelope.
|
||||
|
||||
Example:
|
||||
POST /Service.Method
|
||||
Request:
|
||||
{
|
||||
"requestField1": "value1",
|
||||
"requestField2": "value2",
|
||||
}
|
||||
Response:
|
||||
{
|
||||
"responseField1": "value1",
|
||||
"responseField2": "value2",
|
||||
}
|
||||
|
||||
Check the gorilla/rpc documentation for more details:
|
||||
|
||||
http://gorilla-web.appspot.com/pkg/rpc
|
||||
*/
|
||||
package protorpc
|
87
Godeps/_workspace/src/github.com/gorilla/rpc/v2/protorpc/protorpc_test.go
generated
vendored
87
Godeps/_workspace/src/github.com/gorilla/rpc/v2/protorpc/protorpc_test.go
generated
vendored
@ -1,87 +0,0 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Copyright 2012 The Gorilla Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package protorpc
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/gorilla/rpc/v2"
|
||||
)
|
||||
|
||||
var ErrResponseError = errors.New("response error")
|
||||
|
||||
type Service1Request struct {
|
||||
A int
|
||||
B int
|
||||
}
|
||||
|
||||
type Service1BadRequest struct {
|
||||
}
|
||||
|
||||
type Service1Response struct {
|
||||
Result int
|
||||
ErrorMessage string `json:"error_message"`
|
||||
}
|
||||
|
||||
type Service1 struct {
|
||||
}
|
||||
|
||||
func (t *Service1) Multiply(r *http.Request, req *Service1Request, res *Service1Response) error {
|
||||
res.Result = req.A * req.B
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *Service1) ResponseError(r *http.Request, req *Service1Request, res *Service1Response) error {
|
||||
return ErrResponseError
|
||||
}
|
||||
|
||||
func execute(t *testing.T, s *rpc.Server, method string, req, res interface{}) (int, error) {
|
||||
if !s.HasMethod(method) {
|
||||
t.Fatal("Expected to be registered:", method)
|
||||
}
|
||||
|
||||
buf, _ := json.Marshal(req)
|
||||
body := bytes.NewBuffer(buf)
|
||||
r, _ := http.NewRequest("POST", "http://localhost:8080/"+method, body)
|
||||
r.Header.Set("Content-Type", "application/json")
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
s.ServeHTTP(w, r)
|
||||
|
||||
err := json.NewDecoder(w.Body).Decode(res)
|
||||
return w.Code, err
|
||||
}
|
||||
|
||||
func TestService(t *testing.T) {
|
||||
s := rpc.NewServer()
|
||||
s.RegisterCodec(NewCodec(), "application/json")
|
||||
s.RegisterService(new(Service1), "")
|
||||
|
||||
var res Service1Response
|
||||
if _, err := execute(t, s, "Service1.Multiply", &Service1Request{4, 2}, &res); err != nil {
|
||||
t.Error("Expected err to be nil, but got:", err)
|
||||
}
|
||||
if res.Result != 8 {
|
||||
t.Error("Expected res.Result to be 8, but got:", res.Result)
|
||||
}
|
||||
if res.ErrorMessage != "" {
|
||||
t.Error("Expected error_message to be empty, but got:", res.ErrorMessage)
|
||||
}
|
||||
if code, err := execute(t, s, "Service1.ResponseError", &Service1Request{4, 2}, &res); err != nil || code != 400 {
|
||||
t.Errorf("Expected code to be 400 and error to be nil, but got %v (%v)", code, err)
|
||||
}
|
||||
if res.ErrorMessage == "" {
|
||||
t.Errorf("Expected error_message to be %q, but got %q", ErrResponseError, res.ErrorMessage)
|
||||
}
|
||||
if code, _ := execute(t, s, "Service1.Multiply", nil, &res); code != 400 {
|
||||
t.Error("Expected http response code 400, but got", code)
|
||||
}
|
||||
}
|
147
Godeps/_workspace/src/github.com/gorilla/rpc/v2/protorpc/server.go
generated
vendored
147
Godeps/_workspace/src/github.com/gorilla/rpc/v2/protorpc/server.go
generated
vendored
@ -1,147 +0,0 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Copyright 2012 The Gorilla Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package protorpc
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/gorilla/rpc/v2"
|
||||
)
|
||||
|
||||
var null = json.RawMessage([]byte("null"))
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Request and Response
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// serverRequest represents a ProtoRPC request received by the server.
|
||||
type serverRequest struct {
|
||||
// A String containing the name of the method to be invoked.
|
||||
Method string `json:"method"`
|
||||
// An Array of objects to pass as arguments to the method.
|
||||
Params *json.RawMessage `json:"params"`
|
||||
// The request id. This can be of any type. It is used to match the
|
||||
// response with the request that it is replying to.
|
||||
Id *json.RawMessage `json:"id"`
|
||||
}
|
||||
|
||||
// serverResponse represents a ProtoRPC response returned by the server.
|
||||
type serverResponse struct {
|
||||
// The Object that was returned by the invoked method. This must be null
|
||||
// in case there was an error invoking the method.
|
||||
Result interface{} `json:"result"`
|
||||
// An Error object if there was an error invoking the method. It must be
|
||||
// null if there was no error.
|
||||
Error interface{} `json:"error"`
|
||||
// This must be the same id as the request it is responding to.
|
||||
Id *json.RawMessage `json:"id"`
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Codec
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// NewCodec returns a new ProtoRPC Codec.
|
||||
func NewCodec() *Codec {
|
||||
return &Codec{}
|
||||
}
|
||||
|
||||
// Codec creates a CodecRequest to process each request.
|
||||
type Codec struct {
|
||||
}
|
||||
|
||||
// NewRequest returns a CodecRequest.
|
||||
func (c *Codec) NewRequest(r *http.Request) rpc.CodecRequest {
|
||||
return newCodecRequest(r)
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// CodecRequest
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// newCodecRequest returns a new CodecRequest.
|
||||
func newCodecRequest(r *http.Request) rpc.CodecRequest {
|
||||
// Decode the request body and check if RPC method is valid.
|
||||
req := new(serverRequest)
|
||||
path := r.URL.Path
|
||||
index := strings.LastIndex(path, "/")
|
||||
if index < 0 {
|
||||
return &CodecRequest{request: req, err: fmt.Errorf("rpc: no method: %s", path)}
|
||||
}
|
||||
req.Method = path[index+1:]
|
||||
err := json.NewDecoder(r.Body).Decode(&req.Params)
|
||||
r.Body.Close()
|
||||
var errr error
|
||||
if err != io.EOF {
|
||||
errr = err
|
||||
}
|
||||
return &CodecRequest{request: req, err: errr}
|
||||
}
|
||||
|
||||
// CodecRequest decodes and encodes a single request.
|
||||
type CodecRequest struct {
|
||||
request *serverRequest
|
||||
err error
|
||||
}
|
||||
|
||||
// Method returns the RPC method for the current request.
|
||||
//
|
||||
// The method uses a dotted notation as in "Service.Method".
|
||||
func (c *CodecRequest) Method() (string, error) {
|
||||
if c.err == nil {
|
||||
return c.request.Method, nil
|
||||
}
|
||||
return "", c.err
|
||||
}
|
||||
|
||||
// ReadRequest fills the request object for the RPC method.
|
||||
func (c *CodecRequest) ReadRequest(args interface{}) error {
|
||||
if c.err == nil {
|
||||
if c.request.Params != nil {
|
||||
c.err = json.Unmarshal(*c.request.Params, args)
|
||||
} else {
|
||||
c.err = errors.New("rpc: method request ill-formed: missing params field")
|
||||
}
|
||||
}
|
||||
return c.err
|
||||
}
|
||||
|
||||
// WriteResponse encodes the response and writes it to the ResponseWriter.
|
||||
func (c *CodecRequest) WriteResponse(w http.ResponseWriter, reply interface{}) {
|
||||
res := &serverResponse{
|
||||
Result: reply,
|
||||
Error: &null,
|
||||
Id: c.request.Id,
|
||||
}
|
||||
c.writeServerResponse(w, 200, res)
|
||||
}
|
||||
|
||||
func (c *CodecRequest) WriteError(w http.ResponseWriter, status int, err error) {
|
||||
res := &serverResponse{
|
||||
Result: &struct {
|
||||
ErrorMessage interface{} `json:"error_message"`
|
||||
}{err.Error()},
|
||||
Id: c.request.Id,
|
||||
}
|
||||
c.writeServerResponse(w, status, res)
|
||||
}
|
||||
|
||||
func (c *CodecRequest) writeServerResponse(w http.ResponseWriter, status int, res *serverResponse) {
|
||||
b, err := json.Marshal(res.Result)
|
||||
if err == nil {
|
||||
w.WriteHeader(status)
|
||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||
w.Write(b)
|
||||
} else {
|
||||
// Not sure in which case will this happen. But seems harmless.
|
||||
rpc.WriteError(w, 400, err.Error())
|
||||
}
|
||||
}
|
54
Godeps/_workspace/src/github.com/gorilla/rpc/v2/server_test.go
generated
vendored
54
Godeps/_workspace/src/github.com/gorilla/rpc/v2/server_test.go
generated
vendored
@ -1,54 +0,0 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Copyright 2012 The Gorilla Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package rpc
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type Service1Request struct {
|
||||
A int
|
||||
B int
|
||||
}
|
||||
|
||||
type Service1Response struct {
|
||||
Result int
|
||||
}
|
||||
|
||||
type Service1 struct {
|
||||
}
|
||||
|
||||
func (t *Service1) Multiply(r *http.Request, req *Service1Request, res *Service1Response) error {
|
||||
res.Result = req.A * req.B
|
||||
return nil
|
||||
}
|
||||
|
||||
type Service2 struct {
|
||||
}
|
||||
|
||||
func TestRegisterService(t *testing.T) {
|
||||
var err error
|
||||
s := NewServer()
|
||||
service1 := new(Service1)
|
||||
service2 := new(Service2)
|
||||
|
||||
// Inferred name.
|
||||
err = s.RegisterService(service1, "")
|
||||
if err != nil || !s.HasMethod("Service1.Multiply") {
|
||||
t.Errorf("Expected to be registered: Service1.Multiply")
|
||||
}
|
||||
// Provided name.
|
||||
err = s.RegisterService(service1, "Foo")
|
||||
if err != nil || !s.HasMethod("Foo.Multiply") {
|
||||
t.Errorf("Expected to be registered: Foo.Multiply")
|
||||
}
|
||||
// No methods.
|
||||
err = s.RegisterService(service2, "")
|
||||
if err == nil {
|
||||
t.Errorf("Expected error on service2")
|
||||
}
|
||||
}
|
6
Godeps/_workspace/src/github.com/minio/cli/.travis.yml
generated
vendored
6
Godeps/_workspace/src/github.com/minio/cli/.travis.yml
generated
vendored
@ -1,6 +0,0 @@
|
||||
language: go
|
||||
go: 1.1
|
||||
|
||||
script:
|
||||
- go vet ./...
|
||||
- go test -v ./...
|
587
Godeps/_workspace/src/github.com/minio/cli/app_test.go
generated
vendored
587
Godeps/_workspace/src/github.com/minio/cli/app_test.go
generated
vendored
@ -1,587 +0,0 @@
|
||||
package cli_test
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/minio/cli"
|
||||
)
|
||||
|
||||
func ExampleApp() {
|
||||
// set args for examples sake
|
||||
os.Args = []string{"greet", "--name", "Jeremy"}
|
||||
|
||||
app := cli.NewApp()
|
||||
app.Name = "greet"
|
||||
app.Flags = []cli.Flag{
|
||||
cli.StringFlag{Name: "name", Value: "bob", Usage: "a name to say"},
|
||||
}
|
||||
app.Action = func(c *cli.Context) {
|
||||
fmt.Printf("Hello %v\n", c.String("name"))
|
||||
}
|
||||
app.Author = "Harrison"
|
||||
app.Email = "harrison@lolwut.com"
|
||||
app.Authors = []cli.Author{{Name: "Oliver Allen", Email: "oliver@toyshop.com"}}
|
||||
app.Run(os.Args)
|
||||
// Output:
|
||||
// Hello Jeremy
|
||||
}
|
||||
|
||||
func ExampleAppSubcommand() {
|
||||
// set args for examples sake
|
||||
os.Args = []string{"say", "hi", "english", "--name", "Jeremy"}
|
||||
app := cli.NewApp()
|
||||
app.Name = "say"
|
||||
app.Commands = []cli.Command{
|
||||
{
|
||||
Name: "hello",
|
||||
Aliases: []string{"hi"},
|
||||
Usage: "use it to see a description",
|
||||
Description: "This is how we describe hello the function",
|
||||
Subcommands: []cli.Command{
|
||||
{
|
||||
Name: "english",
|
||||
Aliases: []string{"en"},
|
||||
Usage: "sends a greeting in english",
|
||||
Description: "greets someone in english",
|
||||
Flags: []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "name",
|
||||
Value: "Bob",
|
||||
Usage: "Name of the person to greet",
|
||||
},
|
||||
},
|
||||
Action: func(c *cli.Context) {
|
||||
fmt.Println("Hello,", c.String("name"))
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
app.Run(os.Args)
|
||||
// Output:
|
||||
// Hello, Jeremy
|
||||
}
|
||||
|
||||
func ExampleAppHelp() {
|
||||
// set args for examples sake
|
||||
os.Args = []string{"greet", "h", "describeit"}
|
||||
|
||||
app := cli.NewApp()
|
||||
app.Name = "greet"
|
||||
app.Flags = []cli.Flag{
|
||||
cli.StringFlag{Name: "name", Value: "bob", Usage: "a name to say"},
|
||||
}
|
||||
app.Commands = []cli.Command{
|
||||
{
|
||||
Name: "describeit",
|
||||
Aliases: []string{"d"},
|
||||
Usage: "use it to see a description",
|
||||
Description: "This is how we describe describeit the function",
|
||||
Action: func(c *cli.Context) {
|
||||
fmt.Printf("i like to describe things")
|
||||
},
|
||||
},
|
||||
}
|
||||
app.Run(os.Args)
|
||||
// Output:
|
||||
// NAME:
|
||||
// describeit - use it to see a description
|
||||
//
|
||||
// USAGE:
|
||||
// command describeit [arguments...]
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// This is how we describe describeit the function
|
||||
}
|
||||
|
||||
func TestApp_Run(t *testing.T) {
|
||||
s := ""
|
||||
|
||||
app := cli.NewApp()
|
||||
app.Action = func(c *cli.Context) {
|
||||
s = s + c.Args().First()
|
||||
}
|
||||
|
||||
err := app.Run([]string{"command", "foo"})
|
||||
expect(t, err, nil)
|
||||
err = app.Run([]string{"command", "bar"})
|
||||
expect(t, err, nil)
|
||||
expect(t, s, "foobar")
|
||||
}
|
||||
|
||||
var commandAppTests = []struct {
|
||||
name string
|
||||
expected bool
|
||||
}{
|
||||
{"foobar", true},
|
||||
{"batbaz", true},
|
||||
{"b", true},
|
||||
{"f", true},
|
||||
{"bat", false},
|
||||
{"nothing", false},
|
||||
}
|
||||
|
||||
func TestApp_Command(t *testing.T) {
|
||||
app := cli.NewApp()
|
||||
fooCommand := cli.Command{Name: "foobar", Aliases: []string{"f"}}
|
||||
batCommand := cli.Command{Name: "batbaz", Aliases: []string{"b"}}
|
||||
app.Commands = []cli.Command{
|
||||
fooCommand,
|
||||
batCommand,
|
||||
}
|
||||
|
||||
for _, test := range commandAppTests {
|
||||
expect(t, app.Command(test.name) != nil, test.expected)
|
||||
}
|
||||
}
|
||||
|
||||
func TestApp_CommandWithArgBeforeFlags(t *testing.T) {
|
||||
var parsedOption, firstArg string
|
||||
|
||||
app := cli.NewApp()
|
||||
command := cli.Command{
|
||||
Name: "cmd",
|
||||
Flags: []cli.Flag{
|
||||
cli.StringFlag{Name: "option", Value: "", Usage: "some option"},
|
||||
},
|
||||
Action: func(c *cli.Context) {
|
||||
parsedOption = c.String("option")
|
||||
firstArg = c.Args().First()
|
||||
},
|
||||
}
|
||||
app.Commands = []cli.Command{command}
|
||||
|
||||
app.Run([]string{"", "cmd", "my-arg", "--option", "my-option"})
|
||||
|
||||
expect(t, parsedOption, "my-option")
|
||||
expect(t, firstArg, "my-arg")
|
||||
}
|
||||
|
||||
func TestApp_RunAsSubcommandParseFlags(t *testing.T) {
|
||||
var context *cli.Context
|
||||
|
||||
a := cli.NewApp()
|
||||
a.Commands = []cli.Command{
|
||||
{
|
||||
Name: "foo",
|
||||
Action: func(c *cli.Context) {
|
||||
context = c
|
||||
},
|
||||
Flags: []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "lang",
|
||||
Value: "english",
|
||||
Usage: "language for the greeting",
|
||||
},
|
||||
},
|
||||
Before: func(_ *cli.Context) error { return nil },
|
||||
},
|
||||
}
|
||||
a.Run([]string{"", "foo", "--lang", "spanish", "abcd"})
|
||||
|
||||
expect(t, context.Args().Get(0), "abcd")
|
||||
expect(t, context.String("lang"), "spanish")
|
||||
}
|
||||
|
||||
func TestApp_CommandWithFlagBeforeTerminator(t *testing.T) {
|
||||
var parsedOption string
|
||||
var args []string
|
||||
|
||||
app := cli.NewApp()
|
||||
command := cli.Command{
|
||||
Name: "cmd",
|
||||
Flags: []cli.Flag{
|
||||
cli.StringFlag{Name: "option", Value: "", Usage: "some option"},
|
||||
},
|
||||
Action: func(c *cli.Context) {
|
||||
parsedOption = c.String("option")
|
||||
args = c.Args()
|
||||
},
|
||||
}
|
||||
app.Commands = []cli.Command{command}
|
||||
|
||||
app.Run([]string{"", "cmd", "my-arg", "--option", "my-option", "--", "--notARealFlag"})
|
||||
|
||||
expect(t, parsedOption, "my-option")
|
||||
expect(t, args[0], "my-arg")
|
||||
expect(t, args[1], "--")
|
||||
expect(t, args[2], "--notARealFlag")
|
||||
}
|
||||
|
||||
func TestApp_CommandWithNoFlagBeforeTerminator(t *testing.T) {
|
||||
var args []string
|
||||
|
||||
app := cli.NewApp()
|
||||
command := cli.Command{
|
||||
Name: "cmd",
|
||||
Action: func(c *cli.Context) {
|
||||
args = c.Args()
|
||||
},
|
||||
}
|
||||
app.Commands = []cli.Command{command}
|
||||
|
||||
app.Run([]string{"", "cmd", "my-arg", "--", "notAFlagAtAll"})
|
||||
|
||||
expect(t, args[0], "my-arg")
|
||||
expect(t, args[1], "--")
|
||||
expect(t, args[2], "notAFlagAtAll")
|
||||
}
|
||||
|
||||
func TestApp_Float64Flag(t *testing.T) {
|
||||
var meters float64
|
||||
|
||||
app := cli.NewApp()
|
||||
app.Flags = []cli.Flag{
|
||||
cli.Float64Flag{Name: "height", Value: 1.5, Usage: "Set the height, in meters"},
|
||||
}
|
||||
app.Action = func(c *cli.Context) {
|
||||
meters = c.Float64("height")
|
||||
}
|
||||
|
||||
app.Run([]string{"", "--height", "1.93"})
|
||||
expect(t, meters, 1.93)
|
||||
}
|
||||
|
||||
func TestApp_ParseSliceFlags(t *testing.T) {
|
||||
var parsedOption, firstArg string
|
||||
var parsedIntSlice []int
|
||||
var parsedStringSlice []string
|
||||
|
||||
app := cli.NewApp()
|
||||
command := cli.Command{
|
||||
Name: "cmd",
|
||||
Flags: []cli.Flag{
|
||||
cli.IntSliceFlag{Name: "p", Value: &cli.IntSlice{}, Usage: "set one or more ip addr"},
|
||||
cli.StringSliceFlag{Name: "ip", Value: &cli.StringSlice{}, Usage: "set one or more ports to open"},
|
||||
},
|
||||
Action: func(c *cli.Context) {
|
||||
parsedIntSlice = c.IntSlice("p")
|
||||
parsedStringSlice = c.StringSlice("ip")
|
||||
parsedOption = c.String("option")
|
||||
firstArg = c.Args().First()
|
||||
},
|
||||
}
|
||||
app.Commands = []cli.Command{command}
|
||||
|
||||
app.Run([]string{"", "cmd", "my-arg", "-p", "22", "-p", "80", "-ip", "8.8.8.8", "-ip", "8.8.4.4"})
|
||||
|
||||
IntsEquals := func(a, b []int) bool {
|
||||
if len(a) != len(b) {
|
||||
return false
|
||||
}
|
||||
for i, v := range a {
|
||||
if v != b[i] {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
StrsEquals := func(a, b []string) bool {
|
||||
if len(a) != len(b) {
|
||||
return false
|
||||
}
|
||||
for i, v := range a {
|
||||
if v != b[i] {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
var expectedIntSlice = []int{22, 80}
|
||||
var expectedStringSlice = []string{"8.8.8.8", "8.8.4.4"}
|
||||
|
||||
if !IntsEquals(parsedIntSlice, expectedIntSlice) {
|
||||
t.Errorf("%v does not match %v", parsedIntSlice, expectedIntSlice)
|
||||
}
|
||||
|
||||
if !StrsEquals(parsedStringSlice, expectedStringSlice) {
|
||||
t.Errorf("%v does not match %v", parsedStringSlice, expectedStringSlice)
|
||||
}
|
||||
}
|
||||
|
||||
func TestApp_DefaultStdout(t *testing.T) {
|
||||
app := cli.NewApp()
|
||||
|
||||
if app.Writer != os.Stdout {
|
||||
t.Error("Default output writer not set.")
|
||||
}
|
||||
}
|
||||
|
||||
type mockWriter struct {
|
||||
written []byte
|
||||
}
|
||||
|
||||
func (fw *mockWriter) Write(p []byte) (n int, err error) {
|
||||
if fw.written == nil {
|
||||
fw.written = p
|
||||
} else {
|
||||
fw.written = append(fw.written, p...)
|
||||
}
|
||||
|
||||
return len(p), nil
|
||||
}
|
||||
|
||||
func (fw *mockWriter) GetWritten() (b []byte) {
|
||||
return fw.written
|
||||
}
|
||||
|
||||
func TestApp_SetStdout(t *testing.T) {
|
||||
w := &mockWriter{}
|
||||
|
||||
app := cli.NewApp()
|
||||
app.Name = "test"
|
||||
app.Writer = w
|
||||
|
||||
err := app.Run([]string{"help"})
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("Run error: %s", err)
|
||||
}
|
||||
|
||||
if len(w.written) == 0 {
|
||||
t.Error("App did not write output to desired writer.")
|
||||
}
|
||||
}
|
||||
|
||||
func TestApp_BeforeFunc(t *testing.T) {
|
||||
beforeRun, subcommandRun := false, false
|
||||
beforeError := fmt.Errorf("fail")
|
||||
var err error
|
||||
|
||||
app := cli.NewApp()
|
||||
|
||||
app.Before = func(c *cli.Context) error {
|
||||
beforeRun = true
|
||||
s := c.String("opt")
|
||||
if s == "fail" {
|
||||
return beforeError
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
app.Commands = []cli.Command{
|
||||
{
|
||||
Name: "sub",
|
||||
Action: func(c *cli.Context) {
|
||||
subcommandRun = true
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
app.Flags = []cli.Flag{
|
||||
cli.StringFlag{Name: "opt"},
|
||||
}
|
||||
|
||||
// run with the Before() func succeeding
|
||||
err = app.Run([]string{"command", "--opt", "succeed", "sub"})
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("Run error: %s", err)
|
||||
}
|
||||
|
||||
if beforeRun == false {
|
||||
t.Errorf("Before() not executed when expected")
|
||||
}
|
||||
|
||||
if subcommandRun == false {
|
||||
t.Errorf("Subcommand not executed when expected")
|
||||
}
|
||||
|
||||
// reset
|
||||
beforeRun, subcommandRun = false, false
|
||||
|
||||
// run with the Before() func failing
|
||||
err = app.Run([]string{"command", "--opt", "fail", "sub"})
|
||||
|
||||
// should be the same error produced by the Before func
|
||||
if err != beforeError {
|
||||
t.Errorf("Run error expected, but not received")
|
||||
}
|
||||
|
||||
if beforeRun == false {
|
||||
t.Errorf("Before() not executed when expected")
|
||||
}
|
||||
|
||||
if subcommandRun == true {
|
||||
t.Errorf("Subcommand executed when NOT expected")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestApp_AfterFunc(t *testing.T) {
|
||||
afterRun, subcommandRun := false, false
|
||||
afterError := fmt.Errorf("fail")
|
||||
var err error
|
||||
|
||||
app := cli.NewApp()
|
||||
|
||||
app.After = func(c *cli.Context) error {
|
||||
afterRun = true
|
||||
s := c.String("opt")
|
||||
if s == "fail" {
|
||||
return afterError
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
app.Commands = []cli.Command{
|
||||
{
|
||||
Name: "sub",
|
||||
Action: func(c *cli.Context) {
|
||||
subcommandRun = true
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
app.Flags = []cli.Flag{
|
||||
cli.StringFlag{Name: "opt"},
|
||||
}
|
||||
|
||||
// run with the After() func succeeding
|
||||
err = app.Run([]string{"command", "--opt", "succeed", "sub"})
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("Run error: %s", err)
|
||||
}
|
||||
|
||||
if afterRun == false {
|
||||
t.Errorf("After() not executed when expected")
|
||||
}
|
||||
|
||||
if subcommandRun == false {
|
||||
t.Errorf("Subcommand not executed when expected")
|
||||
}
|
||||
|
||||
// reset
|
||||
afterRun, subcommandRun = false, false
|
||||
|
||||
// run with the Before() func failing
|
||||
err = app.Run([]string{"command", "--opt", "fail", "sub"})
|
||||
|
||||
// should be the same error produced by the Before func
|
||||
if err != afterError {
|
||||
t.Errorf("Run error expected, but not received")
|
||||
}
|
||||
|
||||
if afterRun == false {
|
||||
t.Errorf("After() not executed when expected")
|
||||
}
|
||||
|
||||
if subcommandRun == false {
|
||||
t.Errorf("Subcommand not executed when expected")
|
||||
}
|
||||
}
|
||||
|
||||
func TestAppNoHelpFlag(t *testing.T) {
|
||||
oldFlag := cli.HelpFlag
|
||||
defer func() {
|
||||
cli.HelpFlag = oldFlag
|
||||
}()
|
||||
|
||||
cli.HelpFlag = cli.BoolFlag{}
|
||||
|
||||
app := cli.NewApp()
|
||||
err := app.Run([]string{"test", "-h"})
|
||||
|
||||
if err != flag.ErrHelp {
|
||||
t.Errorf("expected error about missing help flag, but got: %s (%T)", err, err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAppHelpPrinter(t *testing.T) {
|
||||
oldPrinter := cli.HelpPrinter
|
||||
defer func() {
|
||||
cli.HelpPrinter = oldPrinter
|
||||
}()
|
||||
|
||||
var wasCalled = false
|
||||
cli.HelpPrinter = func(template string, data interface{}) {
|
||||
wasCalled = true
|
||||
}
|
||||
|
||||
app := cli.NewApp()
|
||||
app.Run([]string{"-h"})
|
||||
|
||||
if wasCalled == false {
|
||||
t.Errorf("Help printer expected to be called, but was not")
|
||||
}
|
||||
}
|
||||
|
||||
func TestAppVersionPrinter(t *testing.T) {
|
||||
oldPrinter := cli.VersionPrinter
|
||||
defer func() {
|
||||
cli.VersionPrinter = oldPrinter
|
||||
}()
|
||||
|
||||
var wasCalled = false
|
||||
cli.VersionPrinter = func(c *cli.Context) {
|
||||
wasCalled = true
|
||||
}
|
||||
|
||||
app := cli.NewApp()
|
||||
ctx := cli.NewContext(app, nil, nil)
|
||||
cli.ShowVersion(ctx)
|
||||
|
||||
if wasCalled == false {
|
||||
t.Errorf("Version printer expected to be called, but was not")
|
||||
}
|
||||
}
|
||||
|
||||
func TestAppCommandNotFound(t *testing.T) {
|
||||
beforeRun, subcommandRun := false, false
|
||||
app := cli.NewApp()
|
||||
|
||||
app.CommandNotFound = func(c *cli.Context, command string) {
|
||||
beforeRun = true
|
||||
}
|
||||
|
||||
app.Commands = []cli.Command{
|
||||
{
|
||||
Name: "bar",
|
||||
Action: func(c *cli.Context) {
|
||||
subcommandRun = true
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
app.Run([]string{"command", "foo"})
|
||||
|
||||
expect(t, beforeRun, true)
|
||||
expect(t, subcommandRun, false)
|
||||
}
|
||||
|
||||
func TestGlobalFlagsInSubcommands(t *testing.T) {
|
||||
subcommandRun := false
|
||||
app := cli.NewApp()
|
||||
|
||||
app.Flags = []cli.Flag{
|
||||
cli.BoolFlag{Name: "debug, d", Usage: "Enable debugging"},
|
||||
}
|
||||
|
||||
app.Commands = []cli.Command{
|
||||
{
|
||||
Name: "foo",
|
||||
Subcommands: []cli.Command{
|
||||
{
|
||||
Name: "bar",
|
||||
Action: func(c *cli.Context) {
|
||||
if c.GlobalBool("debug") {
|
||||
subcommandRun = true
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
app.Run([]string{"command", "-d", "foo", "bar"})
|
||||
|
||||
expect(t, subcommandRun, true)
|
||||
}
|
13
Godeps/_workspace/src/github.com/minio/cli/autocomplete/bash_autocomplete
generated
vendored
13
Godeps/_workspace/src/github.com/minio/cli/autocomplete/bash_autocomplete
generated
vendored
@ -1,13 +0,0 @@
|
||||
#! /bin/bash
|
||||
|
||||
_cli_bash_autocomplete() {
|
||||
local cur prev opts base
|
||||
COMPREPLY=()
|
||||
cur="${COMP_WORDS[COMP_CWORD]}"
|
||||
prev="${COMP_WORDS[COMP_CWORD-1]}"
|
||||
opts=$( ${COMP_WORDS[@]:0:$COMP_CWORD} --generate-bash-completion )
|
||||
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
|
||||
return 0
|
||||
}
|
||||
|
||||
complete -F _cli_bash_autocomplete $PROG
|
5
Godeps/_workspace/src/github.com/minio/cli/autocomplete/zsh_autocomplete
generated
vendored
5
Godeps/_workspace/src/github.com/minio/cli/autocomplete/zsh_autocomplete
generated
vendored
@ -1,5 +0,0 @@
|
||||
autoload -U compinit && compinit
|
||||
autoload -U bashcompinit && bashcompinit
|
||||
|
||||
script_dir=$(dirname $0)
|
||||
source ${script_dir}/bash_autocomplete
|
100
Godeps/_workspace/src/github.com/minio/cli/cli_test.go
generated
vendored
100
Godeps/_workspace/src/github.com/minio/cli/cli_test.go
generated
vendored
@ -1,100 +0,0 @@
|
||||
package cli_test
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/minio/cli"
|
||||
)
|
||||
|
||||
func Example() {
|
||||
app := cli.NewApp()
|
||||
app.Name = "todo"
|
||||
app.Usage = "task list on the command line"
|
||||
app.Commands = []cli.Command{
|
||||
{
|
||||
Name: "add",
|
||||
Aliases: []string{"a"},
|
||||
Usage: "add a task to the list",
|
||||
Action: func(c *cli.Context) {
|
||||
println("added task: ", c.Args().First())
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "complete",
|
||||
Aliases: []string{"c"},
|
||||
Usage: "complete a task on the list",
|
||||
Action: func(c *cli.Context) {
|
||||
println("completed task: ", c.Args().First())
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
app.Run(os.Args)
|
||||
}
|
||||
|
||||
func ExampleSubcommand() {
|
||||
app := cli.NewApp()
|
||||
app.Name = "say"
|
||||
app.Commands = []cli.Command{
|
||||
{
|
||||
Name: "hello",
|
||||
Aliases: []string{"hi"},
|
||||
Usage: "use it to see a description",
|
||||
Description: "This is how we describe hello the function",
|
||||
Subcommands: []cli.Command{
|
||||
{
|
||||
Name: "english",
|
||||
Aliases: []string{"en"},
|
||||
Usage: "sends a greeting in english",
|
||||
Description: "greets someone in english",
|
||||
Flags: []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "name",
|
||||
Value: "Bob",
|
||||
Usage: "Name of the person to greet",
|
||||
},
|
||||
},
|
||||
Action: func(c *cli.Context) {
|
||||
println("Hello, ", c.String("name"))
|
||||
},
|
||||
}, {
|
||||
Name: "spanish",
|
||||
Aliases: []string{"sp"},
|
||||
Usage: "sends a greeting in spanish",
|
||||
Flags: []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "surname",
|
||||
Value: "Jones",
|
||||
Usage: "Surname of the person to greet",
|
||||
},
|
||||
},
|
||||
Action: func(c *cli.Context) {
|
||||
println("Hola, ", c.String("surname"))
|
||||
},
|
||||
}, {
|
||||
Name: "french",
|
||||
Aliases: []string{"fr"},
|
||||
Usage: "sends a greeting in french",
|
||||
Flags: []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "nickname",
|
||||
Value: "Stevie",
|
||||
Usage: "Nickname of the person to greet",
|
||||
},
|
||||
},
|
||||
Action: func(c *cli.Context) {
|
||||
println("Bonjour, ", c.String("nickname"))
|
||||
},
|
||||
},
|
||||
},
|
||||
}, {
|
||||
Name: "bye",
|
||||
Usage: "says goodbye",
|
||||
Action: func(c *cli.Context) {
|
||||
println("bye")
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
app.Run(os.Args)
|
||||
}
|
49
Godeps/_workspace/src/github.com/minio/cli/command_test.go
generated
vendored
49
Godeps/_workspace/src/github.com/minio/cli/command_test.go
generated
vendored
@ -1,49 +0,0 @@
|
||||
package cli_test
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"testing"
|
||||
|
||||
"github.com/minio/cli"
|
||||
)
|
||||
|
||||
func TestCommandDoNotIgnoreFlags(t *testing.T) {
|
||||
app := cli.NewApp()
|
||||
set := flag.NewFlagSet("test", 0)
|
||||
test := []string{"blah", "blah", "-break"}
|
||||
set.Parse(test)
|
||||
|
||||
c := cli.NewContext(app, set, set)
|
||||
|
||||
command := cli.Command{
|
||||
Name: "test-cmd",
|
||||
Aliases: []string{"tc"},
|
||||
Usage: "this is for testing",
|
||||
Description: "testing",
|
||||
Action: func(_ *cli.Context) {},
|
||||
}
|
||||
err := command.Run(c)
|
||||
|
||||
expect(t, err.Error(), "flag provided but not defined: -break")
|
||||
}
|
||||
|
||||
func TestCommandIgnoreFlags(t *testing.T) {
|
||||
app := cli.NewApp()
|
||||
set := flag.NewFlagSet("test", 0)
|
||||
test := []string{"blah", "blah"}
|
||||
set.Parse(test)
|
||||
|
||||
c := cli.NewContext(app, set, set)
|
||||
|
||||
command := cli.Command{
|
||||
Name: "test-cmd",
|
||||
Aliases: []string{"tc"},
|
||||
Usage: "this is for testing",
|
||||
Description: "testing",
|
||||
Action: func(_ *cli.Context) {},
|
||||
SkipFlagParsing: true,
|
||||
}
|
||||
err := command.Run(c)
|
||||
|
||||
expect(t, err, nil)
|
||||
}
|
111
Godeps/_workspace/src/github.com/minio/cli/context_test.go
generated
vendored
111
Godeps/_workspace/src/github.com/minio/cli/context_test.go
generated
vendored
@ -1,111 +0,0 @@
|
||||
package cli_test
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/minio/cli"
|
||||
)
|
||||
|
||||
func TestNewContext(t *testing.T) {
|
||||
set := flag.NewFlagSet("test", 0)
|
||||
set.Int("myflag", 12, "doc")
|
||||
globalSet := flag.NewFlagSet("test", 0)
|
||||
globalSet.Int("myflag", 42, "doc")
|
||||
command := cli.Command{Name: "mycommand"}
|
||||
c := cli.NewContext(nil, set, globalSet)
|
||||
c.Command = command
|
||||
expect(t, c.Int("myflag"), 12)
|
||||
expect(t, c.GlobalInt("myflag"), 42)
|
||||
expect(t, c.Command.Name, "mycommand")
|
||||
}
|
||||
|
||||
func TestContext_Int(t *testing.T) {
|
||||
set := flag.NewFlagSet("test", 0)
|
||||
set.Int("myflag", 12, "doc")
|
||||
c := cli.NewContext(nil, set, set)
|
||||
expect(t, c.Int("myflag"), 12)
|
||||
}
|
||||
|
||||
func TestContext_Duration(t *testing.T) {
|
||||
set := flag.NewFlagSet("test", 0)
|
||||
set.Duration("myflag", time.Duration(12*time.Second), "doc")
|
||||
c := cli.NewContext(nil, set, set)
|
||||
expect(t, c.Duration("myflag"), time.Duration(12*time.Second))
|
||||
}
|
||||
|
||||
func TestContext_String(t *testing.T) {
|
||||
set := flag.NewFlagSet("test", 0)
|
||||
set.String("myflag", "hello world", "doc")
|
||||
c := cli.NewContext(nil, set, set)
|
||||
expect(t, c.String("myflag"), "hello world")
|
||||
}
|
||||
|
||||
func TestContext_Bool(t *testing.T) {
|
||||
set := flag.NewFlagSet("test", 0)
|
||||
set.Bool("myflag", false, "doc")
|
||||
c := cli.NewContext(nil, set, set)
|
||||
expect(t, c.Bool("myflag"), false)
|
||||
}
|
||||
|
||||
func TestContext_BoolT(t *testing.T) {
|
||||
set := flag.NewFlagSet("test", 0)
|
||||
set.Bool("myflag", true, "doc")
|
||||
c := cli.NewContext(nil, set, set)
|
||||
expect(t, c.BoolT("myflag"), true)
|
||||
}
|
||||
|
||||
func TestContext_Args(t *testing.T) {
|
||||
set := flag.NewFlagSet("test", 0)
|
||||
set.Bool("myflag", false, "doc")
|
||||
c := cli.NewContext(nil, set, set)
|
||||
set.Parse([]string{"--myflag", "bat", "baz"})
|
||||
expect(t, len(c.Args()), 2)
|
||||
expect(t, c.Bool("myflag"), true)
|
||||
}
|
||||
|
||||
func TestContext_IsSet(t *testing.T) {
|
||||
set := flag.NewFlagSet("test", 0)
|
||||
set.Bool("myflag", false, "doc")
|
||||
set.String("otherflag", "hello world", "doc")
|
||||
globalSet := flag.NewFlagSet("test", 0)
|
||||
globalSet.Bool("myflagGlobal", true, "doc")
|
||||
c := cli.NewContext(nil, set, globalSet)
|
||||
set.Parse([]string{"--myflag", "bat", "baz"})
|
||||
globalSet.Parse([]string{"--myflagGlobal", "bat", "baz"})
|
||||
expect(t, c.IsSet("myflag"), true)
|
||||
expect(t, c.IsSet("otherflag"), false)
|
||||
expect(t, c.IsSet("bogusflag"), false)
|
||||
expect(t, c.IsSet("myflagGlobal"), false)
|
||||
}
|
||||
|
||||
func TestContext_GlobalIsSet(t *testing.T) {
|
||||
set := flag.NewFlagSet("test", 0)
|
||||
set.Bool("myflag", false, "doc")
|
||||
set.String("otherflag", "hello world", "doc")
|
||||
globalSet := flag.NewFlagSet("test", 0)
|
||||
globalSet.Bool("myflagGlobal", true, "doc")
|
||||
globalSet.Bool("myflagGlobalUnset", true, "doc")
|
||||
c := cli.NewContext(nil, set, globalSet)
|
||||
set.Parse([]string{"--myflag", "bat", "baz"})
|
||||
globalSet.Parse([]string{"--myflagGlobal", "bat", "baz"})
|
||||
expect(t, c.GlobalIsSet("myflag"), false)
|
||||
expect(t, c.GlobalIsSet("otherflag"), false)
|
||||
expect(t, c.GlobalIsSet("bogusflag"), false)
|
||||
expect(t, c.GlobalIsSet("myflagGlobal"), true)
|
||||
expect(t, c.GlobalIsSet("myflagGlobalUnset"), false)
|
||||
expect(t, c.GlobalIsSet("bogusGlobal"), false)
|
||||
}
|
||||
|
||||
func TestContext_NumFlags(t *testing.T) {
|
||||
set := flag.NewFlagSet("test", 0)
|
||||
set.Bool("myflag", false, "doc")
|
||||
set.String("otherflag", "hello world", "doc")
|
||||
globalSet := flag.NewFlagSet("test", 0)
|
||||
globalSet.Bool("myflagGlobal", true, "doc")
|
||||
c := cli.NewContext(nil, set, globalSet)
|
||||
set.Parse([]string{"--myflag", "--otherflag=foo"})
|
||||
globalSet.Parse([]string{"--myflagGlobal"})
|
||||
expect(t, c.NumFlags(), 2)
|
||||
}
|
742
Godeps/_workspace/src/github.com/minio/cli/flag_test.go
generated
vendored
742
Godeps/_workspace/src/github.com/minio/cli/flag_test.go
generated
vendored
@ -1,742 +0,0 @@
|
||||
package cli_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/minio/cli"
|
||||
)
|
||||
|
||||
var boolFlagTests = []struct {
|
||||
name string
|
||||
expected string
|
||||
}{
|
||||
{"help", "--help\t"},
|
||||
{"h", "-h\t"},
|
||||
}
|
||||
|
||||
func TestBoolFlagHelpOutput(t *testing.T) {
|
||||
|
||||
for _, test := range boolFlagTests {
|
||||
flag := cli.BoolFlag{Name: test.name}
|
||||
output := flag.String()
|
||||
|
||||
if output != test.expected {
|
||||
t.Errorf("%s does not match %s", output, test.expected)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var stringFlagTests = []struct {
|
||||
name string
|
||||
value string
|
||||
expected string
|
||||
}{
|
||||
{"help", "", "--help \t"},
|
||||
{"h", "", "-h \t"},
|
||||
{"h", "", "-h \t"},
|
||||
{"test", "Something", "--test \"Something\"\t"},
|
||||
}
|
||||
|
||||
func TestStringFlagHelpOutput(t *testing.T) {
|
||||
|
||||
for _, test := range stringFlagTests {
|
||||
flag := cli.StringFlag{Name: test.name, Value: test.value}
|
||||
output := flag.String()
|
||||
|
||||
if output != test.expected {
|
||||
t.Errorf("%s does not match %s", output, test.expected)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestStringFlagWithEnvVarHelpOutput(t *testing.T) {
|
||||
os.Clearenv()
|
||||
os.Setenv("APP_FOO", "derp")
|
||||
for _, test := range stringFlagTests {
|
||||
flag := cli.StringFlag{Name: test.name, Value: test.value, EnvVar: "APP_FOO"}
|
||||
output := flag.String()
|
||||
|
||||
if !strings.HasSuffix(output, " [$APP_FOO]") {
|
||||
t.Errorf("%s does not end with [$APP_FOO]", output)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var stringSliceFlagTests = []struct {
|
||||
name string
|
||||
value *cli.StringSlice
|
||||
expected string
|
||||
}{
|
||||
{"help", func() *cli.StringSlice {
|
||||
s := &cli.StringSlice{}
|
||||
s.Set("")
|
||||
return s
|
||||
}(), "--help [--help option --help option]\t"},
|
||||
{"h", func() *cli.StringSlice {
|
||||
s := &cli.StringSlice{}
|
||||
s.Set("")
|
||||
return s
|
||||
}(), "-h [-h option -h option]\t"},
|
||||
{"h", func() *cli.StringSlice {
|
||||
s := &cli.StringSlice{}
|
||||
s.Set("")
|
||||
return s
|
||||
}(), "-h [-h option -h option]\t"},
|
||||
{"test", func() *cli.StringSlice {
|
||||
s := &cli.StringSlice{}
|
||||
s.Set("Something")
|
||||
return s
|
||||
}(), "--test [--test option --test option]\t"},
|
||||
}
|
||||
|
||||
func TestStringSliceFlagHelpOutput(t *testing.T) {
|
||||
|
||||
for _, test := range stringSliceFlagTests {
|
||||
flag := cli.StringSliceFlag{Name: test.name, Value: test.value}
|
||||
output := flag.String()
|
||||
|
||||
if output != test.expected {
|
||||
t.Errorf("%q does not match %q", output, test.expected)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestStringSliceFlagWithEnvVarHelpOutput(t *testing.T) {
|
||||
os.Clearenv()
|
||||
os.Setenv("APP_QWWX", "11,4")
|
||||
for _, test := range stringSliceFlagTests {
|
||||
flag := cli.StringSliceFlag{Name: test.name, Value: test.value, EnvVar: "APP_QWWX"}
|
||||
output := flag.String()
|
||||
|
||||
if !strings.HasSuffix(output, " [$APP_QWWX]") {
|
||||
t.Errorf("%q does not end with [$APP_QWWX]", output)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var intFlagTests = []struct {
|
||||
name string
|
||||
expected string
|
||||
}{
|
||||
{"help", "--help \"0\"\t"},
|
||||
{"h", "-h \"0\"\t"},
|
||||
}
|
||||
|
||||
func TestIntFlagHelpOutput(t *testing.T) {
|
||||
|
||||
for _, test := range intFlagTests {
|
||||
flag := cli.IntFlag{Name: test.name}
|
||||
output := flag.String()
|
||||
|
||||
if output != test.expected {
|
||||
t.Errorf("%s does not match %s", output, test.expected)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestIntFlagWithEnvVarHelpOutput(t *testing.T) {
|
||||
os.Clearenv()
|
||||
os.Setenv("APP_BAR", "2")
|
||||
for _, test := range intFlagTests {
|
||||
flag := cli.IntFlag{Name: test.name, EnvVar: "APP_BAR"}
|
||||
output := flag.String()
|
||||
|
||||
if !strings.HasSuffix(output, " [$APP_BAR]") {
|
||||
t.Errorf("%s does not end with [$APP_BAR]", output)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var durationFlagTests = []struct {
|
||||
name string
|
||||
expected string
|
||||
}{
|
||||
{"help", "--help \"0\"\t"},
|
||||
{"h", "-h \"0\"\t"},
|
||||
}
|
||||
|
||||
func TestDurationFlagHelpOutput(t *testing.T) {
|
||||
|
||||
for _, test := range durationFlagTests {
|
||||
flag := cli.DurationFlag{Name: test.name}
|
||||
output := flag.String()
|
||||
|
||||
if output != test.expected {
|
||||
t.Errorf("%s does not match %s", output, test.expected)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestDurationFlagWithEnvVarHelpOutput(t *testing.T) {
|
||||
os.Clearenv()
|
||||
os.Setenv("APP_BAR", "2h3m6s")
|
||||
for _, test := range durationFlagTests {
|
||||
flag := cli.DurationFlag{Name: test.name, EnvVar: "APP_BAR"}
|
||||
output := flag.String()
|
||||
|
||||
if !strings.HasSuffix(output, " [$APP_BAR]") {
|
||||
t.Errorf("%s does not end with [$APP_BAR]", output)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var intSliceFlagTests = []struct {
|
||||
name string
|
||||
value *cli.IntSlice
|
||||
expected string
|
||||
}{
|
||||
{"help", &cli.IntSlice{}, "--help [--help option --help option]\t"},
|
||||
{"h", &cli.IntSlice{}, "-h [-h option -h option]\t"},
|
||||
{"h", &cli.IntSlice{}, "-h [-h option -h option]\t"},
|
||||
{"test", func() *cli.IntSlice {
|
||||
i := &cli.IntSlice{}
|
||||
i.Set("9")
|
||||
return i
|
||||
}(), "--test [--test option --test option]\t"},
|
||||
}
|
||||
|
||||
func TestIntSliceFlagHelpOutput(t *testing.T) {
|
||||
|
||||
for _, test := range intSliceFlagTests {
|
||||
flag := cli.IntSliceFlag{Name: test.name, Value: test.value}
|
||||
output := flag.String()
|
||||
|
||||
if output != test.expected {
|
||||
t.Errorf("%q does not match %q", output, test.expected)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestIntSliceFlagWithEnvVarHelpOutput(t *testing.T) {
|
||||
os.Clearenv()
|
||||
os.Setenv("APP_SMURF", "42,3")
|
||||
for _, test := range intSliceFlagTests {
|
||||
flag := cli.IntSliceFlag{Name: test.name, Value: test.value, EnvVar: "APP_SMURF"}
|
||||
output := flag.String()
|
||||
|
||||
if !strings.HasSuffix(output, " [$APP_SMURF]") {
|
||||
t.Errorf("%q does not end with [$APP_SMURF]", output)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var float64FlagTests = []struct {
|
||||
name string
|
||||
expected string
|
||||
}{
|
||||
{"help", "--help \"0\"\t"},
|
||||
{"h", "-h \"0\"\t"},
|
||||
}
|
||||
|
||||
func TestFloat64FlagHelpOutput(t *testing.T) {
|
||||
|
||||
for _, test := range float64FlagTests {
|
||||
flag := cli.Float64Flag{Name: test.name}
|
||||
output := flag.String()
|
||||
|
||||
if output != test.expected {
|
||||
t.Errorf("%s does not match %s", output, test.expected)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestFloat64FlagWithEnvVarHelpOutput(t *testing.T) {
|
||||
os.Clearenv()
|
||||
os.Setenv("APP_BAZ", "99.4")
|
||||
for _, test := range float64FlagTests {
|
||||
flag := cli.Float64Flag{Name: test.name, EnvVar: "APP_BAZ"}
|
||||
output := flag.String()
|
||||
|
||||
if !strings.HasSuffix(output, " [$APP_BAZ]") {
|
||||
t.Errorf("%s does not end with [$APP_BAZ]", output)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var genericFlagTests = []struct {
|
||||
name string
|
||||
value cli.Generic
|
||||
expected string
|
||||
}{
|
||||
{"test", &Parser{"abc", "def"}, "--test \"abc,def\"\ttest flag"},
|
||||
{"t", &Parser{"abc", "def"}, "-t \"abc,def\"\ttest flag"},
|
||||
}
|
||||
|
||||
func TestGenericFlagHelpOutput(t *testing.T) {
|
||||
|
||||
for _, test := range genericFlagTests {
|
||||
flag := cli.GenericFlag{Name: test.name, Value: test.value, Usage: "test flag"}
|
||||
output := flag.String()
|
||||
|
||||
if output != test.expected {
|
||||
t.Errorf("%q does not match %q", output, test.expected)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGenericFlagWithEnvVarHelpOutput(t *testing.T) {
|
||||
os.Clearenv()
|
||||
os.Setenv("APP_ZAP", "3")
|
||||
for _, test := range genericFlagTests {
|
||||
flag := cli.GenericFlag{Name: test.name, EnvVar: "APP_ZAP"}
|
||||
output := flag.String()
|
||||
|
||||
if !strings.HasSuffix(output, " [$APP_ZAP]") {
|
||||
t.Errorf("%s does not end with [$APP_ZAP]", output)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseMultiString(t *testing.T) {
|
||||
(&cli.App{
|
||||
Flags: []cli.Flag{
|
||||
cli.StringFlag{Name: "serve, s"},
|
||||
},
|
||||
Action: func(ctx *cli.Context) {
|
||||
if ctx.String("serve") != "10" {
|
||||
t.Errorf("main name not set")
|
||||
}
|
||||
if ctx.String("s") != "10" {
|
||||
t.Errorf("short name not set")
|
||||
}
|
||||
},
|
||||
}).Run([]string{"run", "-s", "10"})
|
||||
}
|
||||
|
||||
func TestParseMultiStringFromEnv(t *testing.T) {
|
||||
os.Clearenv()
|
||||
os.Setenv("APP_COUNT", "20")
|
||||
(&cli.App{
|
||||
Flags: []cli.Flag{
|
||||
cli.StringFlag{Name: "count, c", EnvVar: "APP_COUNT"},
|
||||
},
|
||||
Action: func(ctx *cli.Context) {
|
||||
if ctx.String("count") != "20" {
|
||||
t.Errorf("main name not set")
|
||||
}
|
||||
if ctx.String("c") != "20" {
|
||||
t.Errorf("short name not set")
|
||||
}
|
||||
},
|
||||
}).Run([]string{"run"})
|
||||
}
|
||||
|
||||
func TestParseMultiStringFromEnvCascade(t *testing.T) {
|
||||
os.Clearenv()
|
||||
os.Setenv("APP_COUNT", "20")
|
||||
(&cli.App{
|
||||
Flags: []cli.Flag{
|
||||
cli.StringFlag{Name: "count, c", EnvVar: "COMPAT_COUNT,APP_COUNT"},
|
||||
},
|
||||
Action: func(ctx *cli.Context) {
|
||||
if ctx.String("count") != "20" {
|
||||
t.Errorf("main name not set")
|
||||
}
|
||||
if ctx.String("c") != "20" {
|
||||
t.Errorf("short name not set")
|
||||
}
|
||||
},
|
||||
}).Run([]string{"run"})
|
||||
}
|
||||
|
||||
func TestParseMultiStringSlice(t *testing.T) {
|
||||
(&cli.App{
|
||||
Flags: []cli.Flag{
|
||||
cli.StringSliceFlag{Name: "serve, s", Value: &cli.StringSlice{}},
|
||||
},
|
||||
Action: func(ctx *cli.Context) {
|
||||
if !reflect.DeepEqual(ctx.StringSlice("serve"), []string{"10", "20"}) {
|
||||
t.Errorf("main name not set")
|
||||
}
|
||||
if !reflect.DeepEqual(ctx.StringSlice("s"), []string{"10", "20"}) {
|
||||
t.Errorf("short name not set")
|
||||
}
|
||||
},
|
||||
}).Run([]string{"run", "-s", "10", "-s", "20"})
|
||||
}
|
||||
|
||||
func TestParseMultiStringSliceFromEnv(t *testing.T) {
|
||||
os.Clearenv()
|
||||
os.Setenv("APP_INTERVALS", "20,30,40")
|
||||
|
||||
(&cli.App{
|
||||
Flags: []cli.Flag{
|
||||
cli.StringSliceFlag{Name: "intervals, i", Value: &cli.StringSlice{}, EnvVar: "APP_INTERVALS"},
|
||||
},
|
||||
Action: func(ctx *cli.Context) {
|
||||
if !reflect.DeepEqual(ctx.StringSlice("intervals"), []string{"20", "30", "40"}) {
|
||||
t.Errorf("main name not set from env")
|
||||
}
|
||||
if !reflect.DeepEqual(ctx.StringSlice("i"), []string{"20", "30", "40"}) {
|
||||
t.Errorf("short name not set from env")
|
||||
}
|
||||
},
|
||||
}).Run([]string{"run"})
|
||||
}
|
||||
|
||||
func TestParseMultiStringSliceFromEnvCascade(t *testing.T) {
|
||||
os.Clearenv()
|
||||
os.Setenv("APP_INTERVALS", "20,30,40")
|
||||
|
||||
(&cli.App{
|
||||
Flags: []cli.Flag{
|
||||
cli.StringSliceFlag{Name: "intervals, i", Value: &cli.StringSlice{}, EnvVar: "COMPAT_INTERVALS,APP_INTERVALS"},
|
||||
},
|
||||
Action: func(ctx *cli.Context) {
|
||||
if !reflect.DeepEqual(ctx.StringSlice("intervals"), []string{"20", "30", "40"}) {
|
||||
t.Errorf("main name not set from env")
|
||||
}
|
||||
if !reflect.DeepEqual(ctx.StringSlice("i"), []string{"20", "30", "40"}) {
|
||||
t.Errorf("short name not set from env")
|
||||
}
|
||||
},
|
||||
}).Run([]string{"run"})
|
||||
}
|
||||
|
||||
func TestParseMultiInt(t *testing.T) {
|
||||
a := cli.App{
|
||||
Flags: []cli.Flag{
|
||||
cli.IntFlag{Name: "serve, s"},
|
||||
},
|
||||
Action: func(ctx *cli.Context) {
|
||||
if ctx.Int("serve") != 10 {
|
||||
t.Errorf("main name not set")
|
||||
}
|
||||
if ctx.Int("s") != 10 {
|
||||
t.Errorf("short name not set")
|
||||
}
|
||||
},
|
||||
}
|
||||
a.Run([]string{"run", "-s", "10"})
|
||||
}
|
||||
|
||||
func TestParseMultiIntFromEnv(t *testing.T) {
|
||||
os.Clearenv()
|
||||
os.Setenv("APP_TIMEOUT_SECONDS", "10")
|
||||
a := cli.App{
|
||||
Flags: []cli.Flag{
|
||||
cli.IntFlag{Name: "timeout, t", EnvVar: "APP_TIMEOUT_SECONDS"},
|
||||
},
|
||||
Action: func(ctx *cli.Context) {
|
||||
if ctx.Int("timeout") != 10 {
|
||||
t.Errorf("main name not set")
|
||||
}
|
||||
if ctx.Int("t") != 10 {
|
||||
t.Errorf("short name not set")
|
||||
}
|
||||
},
|
||||
}
|
||||
a.Run([]string{"run"})
|
||||
}
|
||||
|
||||
func TestParseMultiIntFromEnvCascade(t *testing.T) {
|
||||
os.Clearenv()
|
||||
os.Setenv("APP_TIMEOUT_SECONDS", "10")
|
||||
a := cli.App{
|
||||
Flags: []cli.Flag{
|
||||
cli.IntFlag{Name: "timeout, t", EnvVar: "COMPAT_TIMEOUT_SECONDS,APP_TIMEOUT_SECONDS"},
|
||||
},
|
||||
Action: func(ctx *cli.Context) {
|
||||
if ctx.Int("timeout") != 10 {
|
||||
t.Errorf("main name not set")
|
||||
}
|
||||
if ctx.Int("t") != 10 {
|
||||
t.Errorf("short name not set")
|
||||
}
|
||||
},
|
||||
}
|
||||
a.Run([]string{"run"})
|
||||
}
|
||||
|
||||
func TestParseMultiIntSlice(t *testing.T) {
|
||||
(&cli.App{
|
||||
Flags: []cli.Flag{
|
||||
cli.IntSliceFlag{Name: "serve, s", Value: &cli.IntSlice{}},
|
||||
},
|
||||
Action: func(ctx *cli.Context) {
|
||||
if !reflect.DeepEqual(ctx.IntSlice("serve"), []int{10, 20}) {
|
||||
t.Errorf("main name not set")
|
||||
}
|
||||
if !reflect.DeepEqual(ctx.IntSlice("s"), []int{10, 20}) {
|
||||
t.Errorf("short name not set")
|
||||
}
|
||||
},
|
||||
}).Run([]string{"run", "-s", "10", "-s", "20"})
|
||||
}
|
||||
|
||||
func TestParseMultiIntSliceFromEnv(t *testing.T) {
|
||||
os.Clearenv()
|
||||
os.Setenv("APP_INTERVALS", "20,30,40")
|
||||
|
||||
(&cli.App{
|
||||
Flags: []cli.Flag{
|
||||
cli.IntSliceFlag{Name: "intervals, i", Value: &cli.IntSlice{}, EnvVar: "APP_INTERVALS"},
|
||||
},
|
||||
Action: func(ctx *cli.Context) {
|
||||
if !reflect.DeepEqual(ctx.IntSlice("intervals"), []int{20, 30, 40}) {
|
||||
t.Errorf("main name not set from env")
|
||||
}
|
||||
if !reflect.DeepEqual(ctx.IntSlice("i"), []int{20, 30, 40}) {
|
||||
t.Errorf("short name not set from env")
|
||||
}
|
||||
},
|
||||
}).Run([]string{"run"})
|
||||
}
|
||||
|
||||
func TestParseMultiIntSliceFromEnvCascade(t *testing.T) {
|
||||
os.Clearenv()
|
||||
os.Setenv("APP_INTERVALS", "20,30,40")
|
||||
|
||||
(&cli.App{
|
||||
Flags: []cli.Flag{
|
||||
cli.IntSliceFlag{Name: "intervals, i", Value: &cli.IntSlice{}, EnvVar: "COMPAT_INTERVALS,APP_INTERVALS"},
|
||||
},
|
||||
Action: func(ctx *cli.Context) {
|
||||
if !reflect.DeepEqual(ctx.IntSlice("intervals"), []int{20, 30, 40}) {
|
||||
t.Errorf("main name not set from env")
|
||||
}
|
||||
if !reflect.DeepEqual(ctx.IntSlice("i"), []int{20, 30, 40}) {
|
||||
t.Errorf("short name not set from env")
|
||||
}
|
||||
},
|
||||
}).Run([]string{"run"})
|
||||
}
|
||||
|
||||
func TestParseMultiFloat64(t *testing.T) {
|
||||
a := cli.App{
|
||||
Flags: []cli.Flag{
|
||||
cli.Float64Flag{Name: "serve, s"},
|
||||
},
|
||||
Action: func(ctx *cli.Context) {
|
||||
if ctx.Float64("serve") != 10.2 {
|
||||
t.Errorf("main name not set")
|
||||
}
|
||||
if ctx.Float64("s") != 10.2 {
|
||||
t.Errorf("short name not set")
|
||||
}
|
||||
},
|
||||
}
|
||||
a.Run([]string{"run", "-s", "10.2"})
|
||||
}
|
||||
|
||||
func TestParseMultiFloat64FromEnv(t *testing.T) {
|
||||
os.Clearenv()
|
||||
os.Setenv("APP_TIMEOUT_SECONDS", "15.5")
|
||||
a := cli.App{
|
||||
Flags: []cli.Flag{
|
||||
cli.Float64Flag{Name: "timeout, t", EnvVar: "APP_TIMEOUT_SECONDS"},
|
||||
},
|
||||
Action: func(ctx *cli.Context) {
|
||||
if ctx.Float64("timeout") != 15.5 {
|
||||
t.Errorf("main name not set")
|
||||
}
|
||||
if ctx.Float64("t") != 15.5 {
|
||||
t.Errorf("short name not set")
|
||||
}
|
||||
},
|
||||
}
|
||||
a.Run([]string{"run"})
|
||||
}
|
||||
|
||||
func TestParseMultiFloat64FromEnvCascade(t *testing.T) {
|
||||
os.Clearenv()
|
||||
os.Setenv("APP_TIMEOUT_SECONDS", "15.5")
|
||||
a := cli.App{
|
||||
Flags: []cli.Flag{
|
||||
cli.Float64Flag{Name: "timeout, t", EnvVar: "COMPAT_TIMEOUT_SECONDS,APP_TIMEOUT_SECONDS"},
|
||||
},
|
||||
Action: func(ctx *cli.Context) {
|
||||
if ctx.Float64("timeout") != 15.5 {
|
||||
t.Errorf("main name not set")
|
||||
}
|
||||
if ctx.Float64("t") != 15.5 {
|
||||
t.Errorf("short name not set")
|
||||
}
|
||||
},
|
||||
}
|
||||
a.Run([]string{"run"})
|
||||
}
|
||||
|
||||
func TestParseMultiBool(t *testing.T) {
|
||||
a := cli.App{
|
||||
Flags: []cli.Flag{
|
||||
cli.BoolFlag{Name: "serve, s"},
|
||||
},
|
||||
Action: func(ctx *cli.Context) {
|
||||
if ctx.Bool("serve") != true {
|
||||
t.Errorf("main name not set")
|
||||
}
|
||||
if ctx.Bool("s") != true {
|
||||
t.Errorf("short name not set")
|
||||
}
|
||||
},
|
||||
}
|
||||
a.Run([]string{"run", "--serve"})
|
||||
}
|
||||
|
||||
func TestParseMultiBoolFromEnv(t *testing.T) {
|
||||
os.Clearenv()
|
||||
os.Setenv("APP_DEBUG", "1")
|
||||
a := cli.App{
|
||||
Flags: []cli.Flag{
|
||||
cli.BoolFlag{Name: "debug, d", EnvVar: "APP_DEBUG"},
|
||||
},
|
||||
Action: func(ctx *cli.Context) {
|
||||
if ctx.Bool("debug") != true {
|
||||
t.Errorf("main name not set from env")
|
||||
}
|
||||
if ctx.Bool("d") != true {
|
||||
t.Errorf("short name not set from env")
|
||||
}
|
||||
},
|
||||
}
|
||||
a.Run([]string{"run"})
|
||||
}
|
||||
|
||||
func TestParseMultiBoolFromEnvCascade(t *testing.T) {
|
||||
os.Clearenv()
|
||||
os.Setenv("APP_DEBUG", "1")
|
||||
a := cli.App{
|
||||
Flags: []cli.Flag{
|
||||
cli.BoolFlag{Name: "debug, d", EnvVar: "COMPAT_DEBUG,APP_DEBUG"},
|
||||
},
|
||||
Action: func(ctx *cli.Context) {
|
||||
if ctx.Bool("debug") != true {
|
||||
t.Errorf("main name not set from env")
|
||||
}
|
||||
if ctx.Bool("d") != true {
|
||||
t.Errorf("short name not set from env")
|
||||
}
|
||||
},
|
||||
}
|
||||
a.Run([]string{"run"})
|
||||
}
|
||||
|
||||
func TestParseMultiBoolT(t *testing.T) {
|
||||
a := cli.App{
|
||||
Flags: []cli.Flag{
|
||||
cli.BoolTFlag{Name: "serve, s"},
|
||||
},
|
||||
Action: func(ctx *cli.Context) {
|
||||
if ctx.BoolT("serve") != true {
|
||||
t.Errorf("main name not set")
|
||||
}
|
||||
if ctx.BoolT("s") != true {
|
||||
t.Errorf("short name not set")
|
||||
}
|
||||
},
|
||||
}
|
||||
a.Run([]string{"run", "--serve"})
|
||||
}
|
||||
|
||||
func TestParseMultiBoolTFromEnv(t *testing.T) {
|
||||
os.Clearenv()
|
||||
os.Setenv("APP_DEBUG", "0")
|
||||
a := cli.App{
|
||||
Flags: []cli.Flag{
|
||||
cli.BoolTFlag{Name: "debug, d", EnvVar: "APP_DEBUG"},
|
||||
},
|
||||
Action: func(ctx *cli.Context) {
|
||||
if ctx.BoolT("debug") != false {
|
||||
t.Errorf("main name not set from env")
|
||||
}
|
||||
if ctx.BoolT("d") != false {
|
||||
t.Errorf("short name not set from env")
|
||||
}
|
||||
},
|
||||
}
|
||||
a.Run([]string{"run"})
|
||||
}
|
||||
|
||||
func TestParseMultiBoolTFromEnvCascade(t *testing.T) {
|
||||
os.Clearenv()
|
||||
os.Setenv("APP_DEBUG", "0")
|
||||
a := cli.App{
|
||||
Flags: []cli.Flag{
|
||||
cli.BoolTFlag{Name: "debug, d", EnvVar: "COMPAT_DEBUG,APP_DEBUG"},
|
||||
},
|
||||
Action: func(ctx *cli.Context) {
|
||||
if ctx.BoolT("debug") != false {
|
||||
t.Errorf("main name not set from env")
|
||||
}
|
||||
if ctx.BoolT("d") != false {
|
||||
t.Errorf("short name not set from env")
|
||||
}
|
||||
},
|
||||
}
|
||||
a.Run([]string{"run"})
|
||||
}
|
||||
|
||||
type Parser [2]string
|
||||
|
||||
func (p *Parser) Set(value string) error {
|
||||
parts := strings.Split(value, ",")
|
||||
if len(parts) != 2 {
|
||||
return fmt.Errorf("invalid format")
|
||||
}
|
||||
|
||||
(*p)[0] = parts[0]
|
||||
(*p)[1] = parts[1]
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Parser) String() string {
|
||||
return fmt.Sprintf("%s,%s", p[0], p[1])
|
||||
}
|
||||
|
||||
func TestParseGeneric(t *testing.T) {
|
||||
a := cli.App{
|
||||
Flags: []cli.Flag{
|
||||
cli.GenericFlag{Name: "serve, s", Value: &Parser{}},
|
||||
},
|
||||
Action: func(ctx *cli.Context) {
|
||||
if !reflect.DeepEqual(ctx.Generic("serve"), &Parser{"10", "20"}) {
|
||||
t.Errorf("main name not set")
|
||||
}
|
||||
if !reflect.DeepEqual(ctx.Generic("s"), &Parser{"10", "20"}) {
|
||||
t.Errorf("short name not set")
|
||||
}
|
||||
},
|
||||
}
|
||||
a.Run([]string{"run", "-s", "10,20"})
|
||||
}
|
||||
|
||||
func TestParseGenericFromEnv(t *testing.T) {
|
||||
os.Clearenv()
|
||||
os.Setenv("APP_SERVE", "20,30")
|
||||
a := cli.App{
|
||||
Flags: []cli.Flag{
|
||||
cli.GenericFlag{Name: "serve, s", Value: &Parser{}, EnvVar: "APP_SERVE"},
|
||||
},
|
||||
Action: func(ctx *cli.Context) {
|
||||
if !reflect.DeepEqual(ctx.Generic("serve"), &Parser{"20", "30"}) {
|
||||
t.Errorf("main name not set from env")
|
||||
}
|
||||
if !reflect.DeepEqual(ctx.Generic("s"), &Parser{"20", "30"}) {
|
||||
t.Errorf("short name not set from env")
|
||||
}
|
||||
},
|
||||
}
|
||||
a.Run([]string{"run"})
|
||||
}
|
||||
|
||||
func TestParseGenericFromEnvCascade(t *testing.T) {
|
||||
os.Clearenv()
|
||||
os.Setenv("APP_FOO", "99,2000")
|
||||
a := cli.App{
|
||||
Flags: []cli.Flag{
|
||||
cli.GenericFlag{Name: "foos", Value: &Parser{}, EnvVar: "COMPAT_FOO,APP_FOO"},
|
||||
},
|
||||
Action: func(ctx *cli.Context) {
|
||||
if !reflect.DeepEqual(ctx.Generic("foos"), &Parser{"99", "2000"}) {
|
||||
t.Errorf("value not set from env")
|
||||
}
|
||||
},
|
||||
}
|
||||
a.Run([]string{"run"})
|
||||
}
|
19
Godeps/_workspace/src/github.com/minio/cli/helpers_test.go
generated
vendored
19
Godeps/_workspace/src/github.com/minio/cli/helpers_test.go
generated
vendored
@ -1,19 +0,0 @@
|
||||
package cli_test
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
/* Test Helpers */
|
||||
func expect(t *testing.T, a interface{}, b interface{}) {
|
||||
if a != b {
|
||||
t.Errorf("Expected %v (type %v) - Got %v (type %v)", b, reflect.TypeOf(b), a, reflect.TypeOf(a))
|
||||
}
|
||||
}
|
||||
|
||||
func refute(t *testing.T, a interface{}, b interface{}) {
|
||||
if a == b {
|
||||
t.Errorf("Did not expect %v (type %v) - Got %v (type %v)", b, reflect.TypeOf(b), a, reflect.TypeOf(a))
|
||||
}
|
||||
}
|
4
Godeps/_workspace/src/gopkg.in/check.v1/.gitignore
generated
vendored
4
Godeps/_workspace/src/gopkg.in/check.v1/.gitignore
generated
vendored
@ -1,4 +0,0 @@
|
||||
_*
|
||||
*.swp
|
||||
*.[568]
|
||||
[568].out
|
91
Godeps/_workspace/src/gopkg.in/check.v1/benchmark_test.go
generated
vendored
91
Godeps/_workspace/src/gopkg.in/check.v1/benchmark_test.go
generated
vendored
@ -1,91 +0,0 @@
|
||||
// These tests verify the test running logic.
|
||||
|
||||
package check_test
|
||||
|
||||
import (
|
||||
"time"
|
||||
. "gopkg.in/check.v1"
|
||||
)
|
||||
|
||||
var benchmarkS = Suite(&BenchmarkS{})
|
||||
|
||||
type BenchmarkS struct{}
|
||||
|
||||
func (s *BenchmarkS) TestCountSuite(c *C) {
|
||||
suitesRun += 1
|
||||
}
|
||||
|
||||
func (s *BenchmarkS) TestBasicTestTiming(c *C) {
|
||||
helper := FixtureHelper{sleepOn: "Test1", sleep: 1000000 * time.Nanosecond}
|
||||
output := String{}
|
||||
runConf := RunConf{Output: &output, Verbose: true}
|
||||
Run(&helper, &runConf)
|
||||
|
||||
expected := "PASS: check_test\\.go:[0-9]+: FixtureHelper\\.Test1\t0\\.001s\n" +
|
||||
"PASS: check_test\\.go:[0-9]+: FixtureHelper\\.Test2\t0\\.000s\n"
|
||||
c.Assert(output.value, Matches, expected)
|
||||
}
|
||||
|
||||
func (s *BenchmarkS) TestStreamTestTiming(c *C) {
|
||||
helper := FixtureHelper{sleepOn: "SetUpSuite", sleep: 1000000 * time.Nanosecond}
|
||||
output := String{}
|
||||
runConf := RunConf{Output: &output, Stream: true}
|
||||
Run(&helper, &runConf)
|
||||
|
||||
expected := "(?s).*\nPASS: check_test\\.go:[0-9]+: FixtureHelper\\.SetUpSuite\t *0\\.001s\n.*"
|
||||
c.Assert(output.value, Matches, expected)
|
||||
}
|
||||
|
||||
func (s *BenchmarkS) TestBenchmark(c *C) {
|
||||
helper := FixtureHelper{sleep: 100000}
|
||||
output := String{}
|
||||
runConf := RunConf{
|
||||
Output: &output,
|
||||
Benchmark: true,
|
||||
BenchmarkTime: 10000000,
|
||||
Filter: "Benchmark1",
|
||||
}
|
||||
Run(&helper, &runConf)
|
||||
c.Check(helper.calls[0], Equals, "SetUpSuite")
|
||||
c.Check(helper.calls[1], Equals, "SetUpTest")
|
||||
c.Check(helper.calls[2], Equals, "Benchmark1")
|
||||
c.Check(helper.calls[3], Equals, "TearDownTest")
|
||||
c.Check(helper.calls[4], Equals, "SetUpTest")
|
||||
c.Check(helper.calls[5], Equals, "Benchmark1")
|
||||
c.Check(helper.calls[6], Equals, "TearDownTest")
|
||||
// ... and more.
|
||||
|
||||
expected := "PASS: check_test\\.go:[0-9]+: FixtureHelper\\.Benchmark1\t *100\t *[12][0-9]{5} ns/op\n"
|
||||
c.Assert(output.value, Matches, expected)
|
||||
}
|
||||
|
||||
func (s *BenchmarkS) TestBenchmarkBytes(c *C) {
|
||||
helper := FixtureHelper{sleep: 100000}
|
||||
output := String{}
|
||||
runConf := RunConf{
|
||||
Output: &output,
|
||||
Benchmark: true,
|
||||
BenchmarkTime: 10000000,
|
||||
Filter: "Benchmark2",
|
||||
}
|
||||
Run(&helper, &runConf)
|
||||
|
||||
expected := "PASS: check_test\\.go:[0-9]+: FixtureHelper\\.Benchmark2\t *100\t *[12][0-9]{5} ns/op\t *[4-9]\\.[0-9]{2} MB/s\n"
|
||||
c.Assert(output.value, Matches, expected)
|
||||
}
|
||||
|
||||
func (s *BenchmarkS) TestBenchmarkMem(c *C) {
|
||||
helper := FixtureHelper{sleep: 100000}
|
||||
output := String{}
|
||||
runConf := RunConf{
|
||||
Output: &output,
|
||||
Benchmark: true,
|
||||
BenchmarkMem: true,
|
||||
BenchmarkTime: 10000000,
|
||||
Filter: "Benchmark3",
|
||||
}
|
||||
Run(&helper, &runConf)
|
||||
|
||||
expected := "PASS: check_test\\.go:[0-9]+: FixtureHelper\\.Benchmark3\t *100\t *[12][0-9]{5} ns/op\t *[0-9]+ B/op\t *[1-9] allocs/op\n"
|
||||
c.Assert(output.value, Matches, expected)
|
||||
}
|
82
Godeps/_workspace/src/gopkg.in/check.v1/bootstrap_test.go
generated
vendored
82
Godeps/_workspace/src/gopkg.in/check.v1/bootstrap_test.go
generated
vendored
@ -1,82 +0,0 @@
|
||||
// These initial tests are for bootstrapping. They verify that we can
|
||||
// basically use the testing infrastructure itself to check if the test
|
||||
// system is working.
|
||||
//
|
||||
// These tests use will break down the test runner badly in case of
|
||||
// errors because if they simply fail, we can't be sure the developer
|
||||
// will ever see anything (because failing means the failing system
|
||||
// somehow isn't working! :-)
|
||||
//
|
||||
// Do not assume *any* internal functionality works as expected besides
|
||||
// what's actually tested here.
|
||||
|
||||
package check_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"gopkg.in/check.v1"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type BootstrapS struct{}
|
||||
|
||||
var boostrapS = check.Suite(&BootstrapS{})
|
||||
|
||||
func (s *BootstrapS) TestCountSuite(c *check.C) {
|
||||
suitesRun += 1
|
||||
}
|
||||
|
||||
func (s *BootstrapS) TestFailedAndFail(c *check.C) {
|
||||
if c.Failed() {
|
||||
critical("c.Failed() must be false first!")
|
||||
}
|
||||
c.Fail()
|
||||
if !c.Failed() {
|
||||
critical("c.Fail() didn't put the test in a failed state!")
|
||||
}
|
||||
c.Succeed()
|
||||
}
|
||||
|
||||
func (s *BootstrapS) TestFailedAndSucceed(c *check.C) {
|
||||
c.Fail()
|
||||
c.Succeed()
|
||||
if c.Failed() {
|
||||
critical("c.Succeed() didn't put the test back in a non-failed state")
|
||||
}
|
||||
}
|
||||
|
||||
func (s *BootstrapS) TestLogAndGetTestLog(c *check.C) {
|
||||
c.Log("Hello there!")
|
||||
log := c.GetTestLog()
|
||||
if log != "Hello there!\n" {
|
||||
critical(fmt.Sprintf("Log() or GetTestLog() is not working! Got: %#v", log))
|
||||
}
|
||||
}
|
||||
|
||||
func (s *BootstrapS) TestLogfAndGetTestLog(c *check.C) {
|
||||
c.Logf("Hello %v", "there!")
|
||||
log := c.GetTestLog()
|
||||
if log != "Hello there!\n" {
|
||||
critical(fmt.Sprintf("Logf() or GetTestLog() is not working! Got: %#v", log))
|
||||
}
|
||||
}
|
||||
|
||||
func (s *BootstrapS) TestRunShowsErrors(c *check.C) {
|
||||
output := String{}
|
||||
check.Run(&FailHelper{}, &check.RunConf{Output: &output})
|
||||
if strings.Index(output.value, "Expected failure!") == -1 {
|
||||
critical(fmt.Sprintf("RunWithWriter() output did not contain the "+
|
||||
"expected failure! Got: %#v",
|
||||
output.value))
|
||||
}
|
||||
}
|
||||
|
||||
func (s *BootstrapS) TestRunDoesntShowSuccesses(c *check.C) {
|
||||
output := String{}
|
||||
check.Run(&SuccessHelper{}, &check.RunConf{Output: &output})
|
||||
if strings.Index(output.value, "Expected success!") != -1 {
|
||||
critical(fmt.Sprintf("RunWithWriter() output contained a successful "+
|
||||
"test! Got: %#v",
|
||||
output.value))
|
||||
}
|
||||
}
|
207
Godeps/_workspace/src/gopkg.in/check.v1/check_test.go
generated
vendored
207
Godeps/_workspace/src/gopkg.in/check.v1/check_test.go
generated
vendored
@ -1,207 +0,0 @@
|
||||
// This file contains just a few generic helpers which are used by the
|
||||
// other test files.
|
||||
|
||||
package check_test
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"regexp"
|
||||
"runtime"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"gopkg.in/check.v1"
|
||||
)
|
||||
|
||||
// We count the number of suites run at least to get a vague hint that the
|
||||
// test suite is behaving as it should. Otherwise a bug introduced at the
|
||||
// very core of the system could go unperceived.
|
||||
const suitesRunExpected = 8
|
||||
|
||||
var suitesRun int = 0
|
||||
|
||||
func Test(t *testing.T) {
|
||||
check.TestingT(t)
|
||||
if suitesRun != suitesRunExpected && flag.Lookup("check.f").Value.String() == "" {
|
||||
critical(fmt.Sprintf("Expected %d suites to run rather than %d",
|
||||
suitesRunExpected, suitesRun))
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Helper functions.
|
||||
|
||||
// Break down badly. This is used in test cases which can't yet assume
|
||||
// that the fundamental bits are working.
|
||||
func critical(error string) {
|
||||
fmt.Fprintln(os.Stderr, "CRITICAL: "+error)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Return the file line where it's called.
|
||||
func getMyLine() int {
|
||||
if _, _, line, ok := runtime.Caller(1); ok {
|
||||
return line
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Helper type implementing a basic io.Writer for testing output.
|
||||
|
||||
// Type implementing the io.Writer interface for analyzing output.
|
||||
type String struct {
|
||||
value string
|
||||
}
|
||||
|
||||
// The only function required by the io.Writer interface. Will append
|
||||
// written data to the String.value string.
|
||||
func (s *String) Write(p []byte) (n int, err error) {
|
||||
s.value += string(p)
|
||||
return len(p), nil
|
||||
}
|
||||
|
||||
// Trivial wrapper to test errors happening on a different file
|
||||
// than the test itself.
|
||||
func checkEqualWrapper(c *check.C, obtained, expected interface{}) (result bool, line int) {
|
||||
return c.Check(obtained, check.Equals, expected), getMyLine()
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Helper suite for testing basic fail behavior.
|
||||
|
||||
type FailHelper struct {
|
||||
testLine int
|
||||
}
|
||||
|
||||
func (s *FailHelper) TestLogAndFail(c *check.C) {
|
||||
s.testLine = getMyLine() - 1
|
||||
c.Log("Expected failure!")
|
||||
c.Fail()
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Helper suite for testing basic success behavior.
|
||||
|
||||
type SuccessHelper struct{}
|
||||
|
||||
func (s *SuccessHelper) TestLogAndSucceed(c *check.C) {
|
||||
c.Log("Expected success!")
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Helper suite for testing ordering and behavior of fixture.
|
||||
|
||||
type FixtureHelper struct {
|
||||
calls []string
|
||||
panicOn string
|
||||
skip bool
|
||||
skipOnN int
|
||||
sleepOn string
|
||||
sleep time.Duration
|
||||
bytes int64
|
||||
}
|
||||
|
||||
func (s *FixtureHelper) trace(name string, c *check.C) {
|
||||
s.calls = append(s.calls, name)
|
||||
if name == s.panicOn {
|
||||
panic(name)
|
||||
}
|
||||
if s.sleep > 0 && s.sleepOn == name {
|
||||
time.Sleep(s.sleep)
|
||||
}
|
||||
if s.skip && s.skipOnN == len(s.calls)-1 {
|
||||
c.Skip("skipOnN == n")
|
||||
}
|
||||
}
|
||||
|
||||
func (s *FixtureHelper) SetUpSuite(c *check.C) {
|
||||
s.trace("SetUpSuite", c)
|
||||
}
|
||||
|
||||
func (s *FixtureHelper) TearDownSuite(c *check.C) {
|
||||
s.trace("TearDownSuite", c)
|
||||
}
|
||||
|
||||
func (s *FixtureHelper) SetUpTest(c *check.C) {
|
||||
s.trace("SetUpTest", c)
|
||||
}
|
||||
|
||||
func (s *FixtureHelper) TearDownTest(c *check.C) {
|
||||
s.trace("TearDownTest", c)
|
||||
}
|
||||
|
||||
func (s *FixtureHelper) Test1(c *check.C) {
|
||||
s.trace("Test1", c)
|
||||
}
|
||||
|
||||
func (s *FixtureHelper) Test2(c *check.C) {
|
||||
s.trace("Test2", c)
|
||||
}
|
||||
|
||||
func (s *FixtureHelper) Benchmark1(c *check.C) {
|
||||
s.trace("Benchmark1", c)
|
||||
for i := 0; i < c.N; i++ {
|
||||
time.Sleep(s.sleep)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *FixtureHelper) Benchmark2(c *check.C) {
|
||||
s.trace("Benchmark2", c)
|
||||
c.SetBytes(1024)
|
||||
for i := 0; i < c.N; i++ {
|
||||
time.Sleep(s.sleep)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *FixtureHelper) Benchmark3(c *check.C) {
|
||||
var x []int64
|
||||
s.trace("Benchmark3", c)
|
||||
for i := 0; i < c.N; i++ {
|
||||
time.Sleep(s.sleep)
|
||||
x = make([]int64, 5)
|
||||
_ = x
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Helper which checks the state of the test and ensures that it matches
|
||||
// the given expectations. Depends on c.Errorf() working, so shouldn't
|
||||
// be used to test this one function.
|
||||
|
||||
type expectedState struct {
|
||||
name string
|
||||
result interface{}
|
||||
failed bool
|
||||
log string
|
||||
}
|
||||
|
||||
// Verify the state of the test. Note that since this also verifies if
|
||||
// the test is supposed to be in a failed state, no other checks should
|
||||
// be done in addition to what is being tested.
|
||||
func checkState(c *check.C, result interface{}, expected *expectedState) {
|
||||
failed := c.Failed()
|
||||
c.Succeed()
|
||||
log := c.GetTestLog()
|
||||
matched, matchError := regexp.MatchString("^"+expected.log+"$", log)
|
||||
if matchError != nil {
|
||||
c.Errorf("Error in matching expression used in testing %s",
|
||||
expected.name)
|
||||
} else if !matched {
|
||||
c.Errorf("%s logged:\n----------\n%s----------\n\nExpected:\n----------\n%s\n----------",
|
||||
expected.name, log, expected.log)
|
||||
}
|
||||
if result != expected.result {
|
||||
c.Errorf("%s returned %#v rather than %#v",
|
||||
expected.name, result, expected.result)
|
||||
}
|
||||
if failed != expected.failed {
|
||||
if failed {
|
||||
c.Errorf("%s has failed when it shouldn't", expected.name)
|
||||
} else {
|
||||
c.Errorf("%s has not failed when it should", expected.name)
|
||||
}
|
||||
}
|
||||
}
|
272
Godeps/_workspace/src/gopkg.in/check.v1/checkers_test.go
generated
vendored
272
Godeps/_workspace/src/gopkg.in/check.v1/checkers_test.go
generated
vendored
@ -1,272 +0,0 @@
|
||||
package check_test
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"gopkg.in/check.v1"
|
||||
"reflect"
|
||||
"runtime"
|
||||
)
|
||||
|
||||
type CheckersS struct{}
|
||||
|
||||
var _ = check.Suite(&CheckersS{})
|
||||
|
||||
func testInfo(c *check.C, checker check.Checker, name string, paramNames []string) {
|
||||
info := checker.Info()
|
||||
if info.Name != name {
|
||||
c.Fatalf("Got name %s, expected %s", info.Name, name)
|
||||
}
|
||||
if !reflect.DeepEqual(info.Params, paramNames) {
|
||||
c.Fatalf("Got param names %#v, expected %#v", info.Params, paramNames)
|
||||
}
|
||||
}
|
||||
|
||||
func testCheck(c *check.C, checker check.Checker, result bool, error string, params ...interface{}) ([]interface{}, []string) {
|
||||
info := checker.Info()
|
||||
if len(params) != len(info.Params) {
|
||||
c.Fatalf("unexpected param count in test; expected %d got %d", len(info.Params), len(params))
|
||||
}
|
||||
names := append([]string{}, info.Params...)
|
||||
result_, error_ := checker.Check(params, names)
|
||||
if result_ != result || error_ != error {
|
||||
c.Fatalf("%s.Check(%#v) returned (%#v, %#v) rather than (%#v, %#v)",
|
||||
info.Name, params, result_, error_, result, error)
|
||||
}
|
||||
return params, names
|
||||
}
|
||||
|
||||
func (s *CheckersS) TestComment(c *check.C) {
|
||||
bug := check.Commentf("a %d bc", 42)
|
||||
comment := bug.CheckCommentString()
|
||||
if comment != "a 42 bc" {
|
||||
c.Fatalf("Commentf returned %#v", comment)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *CheckersS) TestIsNil(c *check.C) {
|
||||
testInfo(c, check.IsNil, "IsNil", []string{"value"})
|
||||
|
||||
testCheck(c, check.IsNil, true, "", nil)
|
||||
testCheck(c, check.IsNil, false, "", "a")
|
||||
|
||||
testCheck(c, check.IsNil, true, "", (chan int)(nil))
|
||||
testCheck(c, check.IsNil, false, "", make(chan int))
|
||||
testCheck(c, check.IsNil, true, "", (error)(nil))
|
||||
testCheck(c, check.IsNil, false, "", errors.New(""))
|
||||
testCheck(c, check.IsNil, true, "", ([]int)(nil))
|
||||
testCheck(c, check.IsNil, false, "", make([]int, 1))
|
||||
testCheck(c, check.IsNil, false, "", int(0))
|
||||
}
|
||||
|
||||
func (s *CheckersS) TestNotNil(c *check.C) {
|
||||
testInfo(c, check.NotNil, "NotNil", []string{"value"})
|
||||
|
||||
testCheck(c, check.NotNil, false, "", nil)
|
||||
testCheck(c, check.NotNil, true, "", "a")
|
||||
|
||||
testCheck(c, check.NotNil, false, "", (chan int)(nil))
|
||||
testCheck(c, check.NotNil, true, "", make(chan int))
|
||||
testCheck(c, check.NotNil, false, "", (error)(nil))
|
||||
testCheck(c, check.NotNil, true, "", errors.New(""))
|
||||
testCheck(c, check.NotNil, false, "", ([]int)(nil))
|
||||
testCheck(c, check.NotNil, true, "", make([]int, 1))
|
||||
}
|
||||
|
||||
func (s *CheckersS) TestNot(c *check.C) {
|
||||
testInfo(c, check.Not(check.IsNil), "Not(IsNil)", []string{"value"})
|
||||
|
||||
testCheck(c, check.Not(check.IsNil), false, "", nil)
|
||||
testCheck(c, check.Not(check.IsNil), true, "", "a")
|
||||
}
|
||||
|
||||
type simpleStruct struct {
|
||||
i int
|
||||
}
|
||||
|
||||
func (s *CheckersS) TestEquals(c *check.C) {
|
||||
testInfo(c, check.Equals, "Equals", []string{"obtained", "expected"})
|
||||
|
||||
// The simplest.
|
||||
testCheck(c, check.Equals, true, "", 42, 42)
|
||||
testCheck(c, check.Equals, false, "", 42, 43)
|
||||
|
||||
// Different native types.
|
||||
testCheck(c, check.Equals, false, "", int32(42), int64(42))
|
||||
|
||||
// With nil.
|
||||
testCheck(c, check.Equals, false, "", 42, nil)
|
||||
|
||||
// Slices
|
||||
testCheck(c, check.Equals, false, "runtime error: comparing uncomparable type []uint8", []byte{1, 2}, []byte{1, 2})
|
||||
|
||||
// Struct values
|
||||
testCheck(c, check.Equals, true, "", simpleStruct{1}, simpleStruct{1})
|
||||
testCheck(c, check.Equals, false, "", simpleStruct{1}, simpleStruct{2})
|
||||
|
||||
// Struct pointers
|
||||
testCheck(c, check.Equals, false, "", &simpleStruct{1}, &simpleStruct{1})
|
||||
testCheck(c, check.Equals, false, "", &simpleStruct{1}, &simpleStruct{2})
|
||||
}
|
||||
|
||||
func (s *CheckersS) TestDeepEquals(c *check.C) {
|
||||
testInfo(c, check.DeepEquals, "DeepEquals", []string{"obtained", "expected"})
|
||||
|
||||
// The simplest.
|
||||
testCheck(c, check.DeepEquals, true, "", 42, 42)
|
||||
testCheck(c, check.DeepEquals, false, "", 42, 43)
|
||||
|
||||
// Different native types.
|
||||
testCheck(c, check.DeepEquals, false, "", int32(42), int64(42))
|
||||
|
||||
// With nil.
|
||||
testCheck(c, check.DeepEquals, false, "", 42, nil)
|
||||
|
||||
// Slices
|
||||
testCheck(c, check.DeepEquals, true, "", []byte{1, 2}, []byte{1, 2})
|
||||
testCheck(c, check.DeepEquals, false, "", []byte{1, 2}, []byte{1, 3})
|
||||
|
||||
// Struct values
|
||||
testCheck(c, check.DeepEquals, true, "", simpleStruct{1}, simpleStruct{1})
|
||||
testCheck(c, check.DeepEquals, false, "", simpleStruct{1}, simpleStruct{2})
|
||||
|
||||
// Struct pointers
|
||||
testCheck(c, check.DeepEquals, true, "", &simpleStruct{1}, &simpleStruct{1})
|
||||
testCheck(c, check.DeepEquals, false, "", &simpleStruct{1}, &simpleStruct{2})
|
||||
}
|
||||
|
||||
func (s *CheckersS) TestHasLen(c *check.C) {
|
||||
testInfo(c, check.HasLen, "HasLen", []string{"obtained", "n"})
|
||||
|
||||
testCheck(c, check.HasLen, true, "", "abcd", 4)
|
||||
testCheck(c, check.HasLen, true, "", []int{1, 2}, 2)
|
||||
testCheck(c, check.HasLen, false, "", []int{1, 2}, 3)
|
||||
|
||||
testCheck(c, check.HasLen, false, "n must be an int", []int{1, 2}, "2")
|
||||
testCheck(c, check.HasLen, false, "obtained value type has no length", nil, 2)
|
||||
}
|
||||
|
||||
func (s *CheckersS) TestErrorMatches(c *check.C) {
|
||||
testInfo(c, check.ErrorMatches, "ErrorMatches", []string{"value", "regex"})
|
||||
|
||||
testCheck(c, check.ErrorMatches, false, "Error value is nil", nil, "some error")
|
||||
testCheck(c, check.ErrorMatches, false, "Value is not an error", 1, "some error")
|
||||
testCheck(c, check.ErrorMatches, true, "", errors.New("some error"), "some error")
|
||||
testCheck(c, check.ErrorMatches, true, "", errors.New("some error"), "so.*or")
|
||||
|
||||
// Verify params mutation
|
||||
params, names := testCheck(c, check.ErrorMatches, false, "", errors.New("some error"), "other error")
|
||||
c.Assert(params[0], check.Equals, "some error")
|
||||
c.Assert(names[0], check.Equals, "error")
|
||||
}
|
||||
|
||||
func (s *CheckersS) TestMatches(c *check.C) {
|
||||
testInfo(c, check.Matches, "Matches", []string{"value", "regex"})
|
||||
|
||||
// Simple matching
|
||||
testCheck(c, check.Matches, true, "", "abc", "abc")
|
||||
testCheck(c, check.Matches, true, "", "abc", "a.c")
|
||||
|
||||
// Must match fully
|
||||
testCheck(c, check.Matches, false, "", "abc", "ab")
|
||||
testCheck(c, check.Matches, false, "", "abc", "bc")
|
||||
|
||||
// String()-enabled values accepted
|
||||
testCheck(c, check.Matches, true, "", reflect.ValueOf("abc"), "a.c")
|
||||
testCheck(c, check.Matches, false, "", reflect.ValueOf("abc"), "a.d")
|
||||
|
||||
// Some error conditions.
|
||||
testCheck(c, check.Matches, false, "Obtained value is not a string and has no .String()", 1, "a.c")
|
||||
testCheck(c, check.Matches, false, "Can't compile regex: error parsing regexp: missing closing ]: `[c$`", "abc", "a[c")
|
||||
}
|
||||
|
||||
func (s *CheckersS) TestPanics(c *check.C) {
|
||||
testInfo(c, check.Panics, "Panics", []string{"function", "expected"})
|
||||
|
||||
// Some errors.
|
||||
testCheck(c, check.Panics, false, "Function has not panicked", func() bool { return false }, "BOOM")
|
||||
testCheck(c, check.Panics, false, "Function must take zero arguments", 1, "BOOM")
|
||||
|
||||
// Plain strings.
|
||||
testCheck(c, check.Panics, true, "", func() { panic("BOOM") }, "BOOM")
|
||||
testCheck(c, check.Panics, false, "", func() { panic("KABOOM") }, "BOOM")
|
||||
testCheck(c, check.Panics, true, "", func() bool { panic("BOOM") }, "BOOM")
|
||||
|
||||
// Error values.
|
||||
testCheck(c, check.Panics, true, "", func() { panic(errors.New("BOOM")) }, errors.New("BOOM"))
|
||||
testCheck(c, check.Panics, false, "", func() { panic(errors.New("KABOOM")) }, errors.New("BOOM"))
|
||||
|
||||
type deep struct{ i int }
|
||||
// Deep value
|
||||
testCheck(c, check.Panics, true, "", func() { panic(&deep{99}) }, &deep{99})
|
||||
|
||||
// Verify params/names mutation
|
||||
params, names := testCheck(c, check.Panics, false, "", func() { panic(errors.New("KABOOM")) }, errors.New("BOOM"))
|
||||
c.Assert(params[0], check.ErrorMatches, "KABOOM")
|
||||
c.Assert(names[0], check.Equals, "panic")
|
||||
|
||||
// Verify a nil panic
|
||||
testCheck(c, check.Panics, true, "", func() { panic(nil) }, nil)
|
||||
testCheck(c, check.Panics, false, "", func() { panic(nil) }, "NOPE")
|
||||
}
|
||||
|
||||
func (s *CheckersS) TestPanicMatches(c *check.C) {
|
||||
testInfo(c, check.PanicMatches, "PanicMatches", []string{"function", "expected"})
|
||||
|
||||
// Error matching.
|
||||
testCheck(c, check.PanicMatches, true, "", func() { panic(errors.New("BOOM")) }, "BO.M")
|
||||
testCheck(c, check.PanicMatches, false, "", func() { panic(errors.New("KABOOM")) }, "BO.M")
|
||||
|
||||
// Some errors.
|
||||
testCheck(c, check.PanicMatches, false, "Function has not panicked", func() bool { return false }, "BOOM")
|
||||
testCheck(c, check.PanicMatches, false, "Function must take zero arguments", 1, "BOOM")
|
||||
|
||||
// Plain strings.
|
||||
testCheck(c, check.PanicMatches, true, "", func() { panic("BOOM") }, "BO.M")
|
||||
testCheck(c, check.PanicMatches, false, "", func() { panic("KABOOM") }, "BOOM")
|
||||
testCheck(c, check.PanicMatches, true, "", func() bool { panic("BOOM") }, "BO.M")
|
||||
|
||||
// Verify params/names mutation
|
||||
params, names := testCheck(c, check.PanicMatches, false, "", func() { panic(errors.New("KABOOM")) }, "BOOM")
|
||||
c.Assert(params[0], check.Equals, "KABOOM")
|
||||
c.Assert(names[0], check.Equals, "panic")
|
||||
|
||||
// Verify a nil panic
|
||||
testCheck(c, check.PanicMatches, false, "Panic value is not a string or an error", func() { panic(nil) }, "")
|
||||
}
|
||||
|
||||
func (s *CheckersS) TestFitsTypeOf(c *check.C) {
|
||||
testInfo(c, check.FitsTypeOf, "FitsTypeOf", []string{"obtained", "sample"})
|
||||
|
||||
// Basic types
|
||||
testCheck(c, check.FitsTypeOf, true, "", 1, 0)
|
||||
testCheck(c, check.FitsTypeOf, false, "", 1, int64(0))
|
||||
|
||||
// Aliases
|
||||
testCheck(c, check.FitsTypeOf, false, "", 1, errors.New(""))
|
||||
testCheck(c, check.FitsTypeOf, false, "", "error", errors.New(""))
|
||||
testCheck(c, check.FitsTypeOf, true, "", errors.New("error"), errors.New(""))
|
||||
|
||||
// Structures
|
||||
testCheck(c, check.FitsTypeOf, false, "", 1, simpleStruct{})
|
||||
testCheck(c, check.FitsTypeOf, false, "", simpleStruct{42}, &simpleStruct{})
|
||||
testCheck(c, check.FitsTypeOf, true, "", simpleStruct{42}, simpleStruct{})
|
||||
testCheck(c, check.FitsTypeOf, true, "", &simpleStruct{42}, &simpleStruct{})
|
||||
|
||||
// Some bad values
|
||||
testCheck(c, check.FitsTypeOf, false, "Invalid sample value", 1, interface{}(nil))
|
||||
testCheck(c, check.FitsTypeOf, false, "", interface{}(nil), 0)
|
||||
}
|
||||
|
||||
func (s *CheckersS) TestImplements(c *check.C) {
|
||||
testInfo(c, check.Implements, "Implements", []string{"obtained", "ifaceptr"})
|
||||
|
||||
var e error
|
||||
var re runtime.Error
|
||||
testCheck(c, check.Implements, true, "", errors.New(""), &e)
|
||||
testCheck(c, check.Implements, false, "", errors.New(""), &re)
|
||||
|
||||
// Some bad values
|
||||
testCheck(c, check.Implements, false, "ifaceptr should be a pointer to an interface variable", 0, errors.New(""))
|
||||
testCheck(c, check.Implements, false, "ifaceptr should be a pointer to an interface variable", 0, interface{}(nil))
|
||||
testCheck(c, check.Implements, false, "", interface{}(nil), &e)
|
||||
}
|
9
Godeps/_workspace/src/gopkg.in/check.v1/export_test.go
generated
vendored
9
Godeps/_workspace/src/gopkg.in/check.v1/export_test.go
generated
vendored
@ -1,9 +0,0 @@
|
||||
package check
|
||||
|
||||
func PrintLine(filename string, line int) (string, error) {
|
||||
return printLine(filename, line)
|
||||
}
|
||||
|
||||
func Indent(s, with string) string {
|
||||
return indent(s, with)
|
||||
}
|
484
Godeps/_workspace/src/gopkg.in/check.v1/fixture_test.go
generated
vendored
484
Godeps/_workspace/src/gopkg.in/check.v1/fixture_test.go
generated
vendored
@ -1,484 +0,0 @@
|
||||
// Tests for the behavior of the test fixture system.
|
||||
|
||||
package check_test
|
||||
|
||||
import (
|
||||
. "gopkg.in/check.v1"
|
||||
)
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Fixture test suite.
|
||||
|
||||
type FixtureS struct{}
|
||||
|
||||
var fixtureS = Suite(&FixtureS{})
|
||||
|
||||
func (s *FixtureS) TestCountSuite(c *C) {
|
||||
suitesRun += 1
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Basic fixture ordering verification.
|
||||
|
||||
func (s *FixtureS) TestOrder(c *C) {
|
||||
helper := FixtureHelper{}
|
||||
Run(&helper, nil)
|
||||
c.Check(helper.calls[0], Equals, "SetUpSuite")
|
||||
c.Check(helper.calls[1], Equals, "SetUpTest")
|
||||
c.Check(helper.calls[2], Equals, "Test1")
|
||||
c.Check(helper.calls[3], Equals, "TearDownTest")
|
||||
c.Check(helper.calls[4], Equals, "SetUpTest")
|
||||
c.Check(helper.calls[5], Equals, "Test2")
|
||||
c.Check(helper.calls[6], Equals, "TearDownTest")
|
||||
c.Check(helper.calls[7], Equals, "TearDownSuite")
|
||||
c.Check(len(helper.calls), Equals, 8)
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Check the behavior when panics occur within tests and fixtures.
|
||||
|
||||
func (s *FixtureS) TestPanicOnTest(c *C) {
|
||||
helper := FixtureHelper{panicOn: "Test1"}
|
||||
output := String{}
|
||||
Run(&helper, &RunConf{Output: &output})
|
||||
c.Check(helper.calls[0], Equals, "SetUpSuite")
|
||||
c.Check(helper.calls[1], Equals, "SetUpTest")
|
||||
c.Check(helper.calls[2], Equals, "Test1")
|
||||
c.Check(helper.calls[3], Equals, "TearDownTest")
|
||||
c.Check(helper.calls[4], Equals, "SetUpTest")
|
||||
c.Check(helper.calls[5], Equals, "Test2")
|
||||
c.Check(helper.calls[6], Equals, "TearDownTest")
|
||||
c.Check(helper.calls[7], Equals, "TearDownSuite")
|
||||
c.Check(len(helper.calls), Equals, 8)
|
||||
|
||||
expected := "^\n-+\n" +
|
||||
"PANIC: check_test\\.go:[0-9]+: FixtureHelper.Test1\n\n" +
|
||||
"\\.\\.\\. Panic: Test1 \\(PC=[xA-F0-9]+\\)\n\n" +
|
||||
".+:[0-9]+\n" +
|
||||
" in (go)?panic\n" +
|
||||
".*check_test.go:[0-9]+\n" +
|
||||
" in FixtureHelper.trace\n" +
|
||||
".*check_test.go:[0-9]+\n" +
|
||||
" in FixtureHelper.Test1\n" +
|
||||
"(.|\n)*$"
|
||||
|
||||
c.Check(output.value, Matches, expected)
|
||||
}
|
||||
|
||||
func (s *FixtureS) TestPanicOnSetUpTest(c *C) {
|
||||
helper := FixtureHelper{panicOn: "SetUpTest"}
|
||||
output := String{}
|
||||
Run(&helper, &RunConf{Output: &output})
|
||||
c.Check(helper.calls[0], Equals, "SetUpSuite")
|
||||
c.Check(helper.calls[1], Equals, "SetUpTest")
|
||||
c.Check(helper.calls[2], Equals, "TearDownTest")
|
||||
c.Check(helper.calls[3], Equals, "TearDownSuite")
|
||||
c.Check(len(helper.calls), Equals, 4)
|
||||
|
||||
expected := "^\n-+\n" +
|
||||
"PANIC: check_test\\.go:[0-9]+: " +
|
||||
"FixtureHelper\\.SetUpTest\n\n" +
|
||||
"\\.\\.\\. Panic: SetUpTest \\(PC=[xA-F0-9]+\\)\n\n" +
|
||||
".+:[0-9]+\n" +
|
||||
" in (go)?panic\n" +
|
||||
".*check_test.go:[0-9]+\n" +
|
||||
" in FixtureHelper.trace\n" +
|
||||
".*check_test.go:[0-9]+\n" +
|
||||
" in FixtureHelper.SetUpTest\n" +
|
||||
"(.|\n)*" +
|
||||
"\n-+\n" +
|
||||
"PANIC: check_test\\.go:[0-9]+: " +
|
||||
"FixtureHelper\\.Test1\n\n" +
|
||||
"\\.\\.\\. Panic: Fixture has panicked " +
|
||||
"\\(see related PANIC\\)\n$"
|
||||
|
||||
c.Check(output.value, Matches, expected)
|
||||
}
|
||||
|
||||
func (s *FixtureS) TestPanicOnTearDownTest(c *C) {
|
||||
helper := FixtureHelper{panicOn: "TearDownTest"}
|
||||
output := String{}
|
||||
Run(&helper, &RunConf{Output: &output})
|
||||
c.Check(helper.calls[0], Equals, "SetUpSuite")
|
||||
c.Check(helper.calls[1], Equals, "SetUpTest")
|
||||
c.Check(helper.calls[2], Equals, "Test1")
|
||||
c.Check(helper.calls[3], Equals, "TearDownTest")
|
||||
c.Check(helper.calls[4], Equals, "TearDownSuite")
|
||||
c.Check(len(helper.calls), Equals, 5)
|
||||
|
||||
expected := "^\n-+\n" +
|
||||
"PANIC: check_test\\.go:[0-9]+: " +
|
||||
"FixtureHelper.TearDownTest\n\n" +
|
||||
"\\.\\.\\. Panic: TearDownTest \\(PC=[xA-F0-9]+\\)\n\n" +
|
||||
".+:[0-9]+\n" +
|
||||
" in (go)?panic\n" +
|
||||
".*check_test.go:[0-9]+\n" +
|
||||
" in FixtureHelper.trace\n" +
|
||||
".*check_test.go:[0-9]+\n" +
|
||||
" in FixtureHelper.TearDownTest\n" +
|
||||
"(.|\n)*" +
|
||||
"\n-+\n" +
|
||||
"PANIC: check_test\\.go:[0-9]+: " +
|
||||
"FixtureHelper\\.Test1\n\n" +
|
||||
"\\.\\.\\. Panic: Fixture has panicked " +
|
||||
"\\(see related PANIC\\)\n$"
|
||||
|
||||
c.Check(output.value, Matches, expected)
|
||||
}
|
||||
|
||||
func (s *FixtureS) TestPanicOnSetUpSuite(c *C) {
|
||||
helper := FixtureHelper{panicOn: "SetUpSuite"}
|
||||
output := String{}
|
||||
Run(&helper, &RunConf{Output: &output})
|
||||
c.Check(helper.calls[0], Equals, "SetUpSuite")
|
||||
c.Check(helper.calls[1], Equals, "TearDownSuite")
|
||||
c.Check(len(helper.calls), Equals, 2)
|
||||
|
||||
expected := "^\n-+\n" +
|
||||
"PANIC: check_test\\.go:[0-9]+: " +
|
||||
"FixtureHelper.SetUpSuite\n\n" +
|
||||
"\\.\\.\\. Panic: SetUpSuite \\(PC=[xA-F0-9]+\\)\n\n" +
|
||||
".+:[0-9]+\n" +
|
||||
" in (go)?panic\n" +
|
||||
".*check_test.go:[0-9]+\n" +
|
||||
" in FixtureHelper.trace\n" +
|
||||
".*check_test.go:[0-9]+\n" +
|
||||
" in FixtureHelper.SetUpSuite\n" +
|
||||
"(.|\n)*$"
|
||||
|
||||
c.Check(output.value, Matches, expected)
|
||||
}
|
||||
|
||||
func (s *FixtureS) TestPanicOnTearDownSuite(c *C) {
|
||||
helper := FixtureHelper{panicOn: "TearDownSuite"}
|
||||
output := String{}
|
||||
Run(&helper, &RunConf{Output: &output})
|
||||
c.Check(helper.calls[0], Equals, "SetUpSuite")
|
||||
c.Check(helper.calls[1], Equals, "SetUpTest")
|
||||
c.Check(helper.calls[2], Equals, "Test1")
|
||||
c.Check(helper.calls[3], Equals, "TearDownTest")
|
||||
c.Check(helper.calls[4], Equals, "SetUpTest")
|
||||
c.Check(helper.calls[5], Equals, "Test2")
|
||||
c.Check(helper.calls[6], Equals, "TearDownTest")
|
||||
c.Check(helper.calls[7], Equals, "TearDownSuite")
|
||||
c.Check(len(helper.calls), Equals, 8)
|
||||
|
||||
expected := "^\n-+\n" +
|
||||
"PANIC: check_test\\.go:[0-9]+: " +
|
||||
"FixtureHelper.TearDownSuite\n\n" +
|
||||
"\\.\\.\\. Panic: TearDownSuite \\(PC=[xA-F0-9]+\\)\n\n" +
|
||||
".+:[0-9]+\n" +
|
||||
" in (go)?panic\n" +
|
||||
".*check_test.go:[0-9]+\n" +
|
||||
" in FixtureHelper.trace\n" +
|
||||
".*check_test.go:[0-9]+\n" +
|
||||
" in FixtureHelper.TearDownSuite\n" +
|
||||
"(.|\n)*$"
|
||||
|
||||
c.Check(output.value, Matches, expected)
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// A wrong argument on a test or fixture will produce a nice error.
|
||||
|
||||
func (s *FixtureS) TestPanicOnWrongTestArg(c *C) {
|
||||
helper := WrongTestArgHelper{}
|
||||
output := String{}
|
||||
Run(&helper, &RunConf{Output: &output})
|
||||
c.Check(helper.calls[0], Equals, "SetUpSuite")
|
||||
c.Check(helper.calls[1], Equals, "SetUpTest")
|
||||
c.Check(helper.calls[2], Equals, "TearDownTest")
|
||||
c.Check(helper.calls[3], Equals, "SetUpTest")
|
||||
c.Check(helper.calls[4], Equals, "Test2")
|
||||
c.Check(helper.calls[5], Equals, "TearDownTest")
|
||||
c.Check(helper.calls[6], Equals, "TearDownSuite")
|
||||
c.Check(len(helper.calls), Equals, 7)
|
||||
|
||||
expected := "^\n-+\n" +
|
||||
"PANIC: fixture_test\\.go:[0-9]+: " +
|
||||
"WrongTestArgHelper\\.Test1\n\n" +
|
||||
"\\.\\.\\. Panic: WrongTestArgHelper\\.Test1 argument " +
|
||||
"should be \\*check\\.C\n"
|
||||
|
||||
c.Check(output.value, Matches, expected)
|
||||
}
|
||||
|
||||
func (s *FixtureS) TestPanicOnWrongSetUpTestArg(c *C) {
|
||||
helper := WrongSetUpTestArgHelper{}
|
||||
output := String{}
|
||||
Run(&helper, &RunConf{Output: &output})
|
||||
c.Check(len(helper.calls), Equals, 0)
|
||||
|
||||
expected :=
|
||||
"^\n-+\n" +
|
||||
"PANIC: fixture_test\\.go:[0-9]+: " +
|
||||
"WrongSetUpTestArgHelper\\.SetUpTest\n\n" +
|
||||
"\\.\\.\\. Panic: WrongSetUpTestArgHelper\\.SetUpTest argument " +
|
||||
"should be \\*check\\.C\n"
|
||||
|
||||
c.Check(output.value, Matches, expected)
|
||||
}
|
||||
|
||||
func (s *FixtureS) TestPanicOnWrongSetUpSuiteArg(c *C) {
|
||||
helper := WrongSetUpSuiteArgHelper{}
|
||||
output := String{}
|
||||
Run(&helper, &RunConf{Output: &output})
|
||||
c.Check(len(helper.calls), Equals, 0)
|
||||
|
||||
expected :=
|
||||
"^\n-+\n" +
|
||||
"PANIC: fixture_test\\.go:[0-9]+: " +
|
||||
"WrongSetUpSuiteArgHelper\\.SetUpSuite\n\n" +
|
||||
"\\.\\.\\. Panic: WrongSetUpSuiteArgHelper\\.SetUpSuite argument " +
|
||||
"should be \\*check\\.C\n"
|
||||
|
||||
c.Check(output.value, Matches, expected)
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Nice errors also when tests or fixture have wrong arg count.
|
||||
|
||||
func (s *FixtureS) TestPanicOnWrongTestArgCount(c *C) {
|
||||
helper := WrongTestArgCountHelper{}
|
||||
output := String{}
|
||||
Run(&helper, &RunConf{Output: &output})
|
||||
c.Check(helper.calls[0], Equals, "SetUpSuite")
|
||||
c.Check(helper.calls[1], Equals, "SetUpTest")
|
||||
c.Check(helper.calls[2], Equals, "TearDownTest")
|
||||
c.Check(helper.calls[3], Equals, "SetUpTest")
|
||||
c.Check(helper.calls[4], Equals, "Test2")
|
||||
c.Check(helper.calls[5], Equals, "TearDownTest")
|
||||
c.Check(helper.calls[6], Equals, "TearDownSuite")
|
||||
c.Check(len(helper.calls), Equals, 7)
|
||||
|
||||
expected := "^\n-+\n" +
|
||||
"PANIC: fixture_test\\.go:[0-9]+: " +
|
||||
"WrongTestArgCountHelper\\.Test1\n\n" +
|
||||
"\\.\\.\\. Panic: WrongTestArgCountHelper\\.Test1 argument " +
|
||||
"should be \\*check\\.C\n"
|
||||
|
||||
c.Check(output.value, Matches, expected)
|
||||
}
|
||||
|
||||
func (s *FixtureS) TestPanicOnWrongSetUpTestArgCount(c *C) {
|
||||
helper := WrongSetUpTestArgCountHelper{}
|
||||
output := String{}
|
||||
Run(&helper, &RunConf{Output: &output})
|
||||
c.Check(len(helper.calls), Equals, 0)
|
||||
|
||||
expected :=
|
||||
"^\n-+\n" +
|
||||
"PANIC: fixture_test\\.go:[0-9]+: " +
|
||||
"WrongSetUpTestArgCountHelper\\.SetUpTest\n\n" +
|
||||
"\\.\\.\\. Panic: WrongSetUpTestArgCountHelper\\.SetUpTest argument " +
|
||||
"should be \\*check\\.C\n"
|
||||
|
||||
c.Check(output.value, Matches, expected)
|
||||
}
|
||||
|
||||
func (s *FixtureS) TestPanicOnWrongSetUpSuiteArgCount(c *C) {
|
||||
helper := WrongSetUpSuiteArgCountHelper{}
|
||||
output := String{}
|
||||
Run(&helper, &RunConf{Output: &output})
|
||||
c.Check(len(helper.calls), Equals, 0)
|
||||
|
||||
expected :=
|
||||
"^\n-+\n" +
|
||||
"PANIC: fixture_test\\.go:[0-9]+: " +
|
||||
"WrongSetUpSuiteArgCountHelper\\.SetUpSuite\n\n" +
|
||||
"\\.\\.\\. Panic: WrongSetUpSuiteArgCountHelper" +
|
||||
"\\.SetUpSuite argument should be \\*check\\.C\n"
|
||||
|
||||
c.Check(output.value, Matches, expected)
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Helper test suites with wrong function arguments.
|
||||
|
||||
type WrongTestArgHelper struct {
|
||||
FixtureHelper
|
||||
}
|
||||
|
||||
func (s *WrongTestArgHelper) Test1(t int) {
|
||||
}
|
||||
|
||||
type WrongSetUpTestArgHelper struct {
|
||||
FixtureHelper
|
||||
}
|
||||
|
||||
func (s *WrongSetUpTestArgHelper) SetUpTest(t int) {
|
||||
}
|
||||
|
||||
type WrongSetUpSuiteArgHelper struct {
|
||||
FixtureHelper
|
||||
}
|
||||
|
||||
func (s *WrongSetUpSuiteArgHelper) SetUpSuite(t int) {
|
||||
}
|
||||
|
||||
type WrongTestArgCountHelper struct {
|
||||
FixtureHelper
|
||||
}
|
||||
|
||||
func (s *WrongTestArgCountHelper) Test1(c *C, i int) {
|
||||
}
|
||||
|
||||
type WrongSetUpTestArgCountHelper struct {
|
||||
FixtureHelper
|
||||
}
|
||||
|
||||
func (s *WrongSetUpTestArgCountHelper) SetUpTest(c *C, i int) {
|
||||
}
|
||||
|
||||
type WrongSetUpSuiteArgCountHelper struct {
|
||||
FixtureHelper
|
||||
}
|
||||
|
||||
func (s *WrongSetUpSuiteArgCountHelper) SetUpSuite(c *C, i int) {
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Ensure fixture doesn't run without tests.
|
||||
|
||||
type NoTestsHelper struct {
|
||||
hasRun bool
|
||||
}
|
||||
|
||||
func (s *NoTestsHelper) SetUpSuite(c *C) {
|
||||
s.hasRun = true
|
||||
}
|
||||
|
||||
func (s *NoTestsHelper) TearDownSuite(c *C) {
|
||||
s.hasRun = true
|
||||
}
|
||||
|
||||
func (s *FixtureS) TestFixtureDoesntRunWithoutTests(c *C) {
|
||||
helper := NoTestsHelper{}
|
||||
output := String{}
|
||||
Run(&helper, &RunConf{Output: &output})
|
||||
c.Check(helper.hasRun, Equals, false)
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Verify that checks and assertions work correctly inside the fixture.
|
||||
|
||||
type FixtureCheckHelper struct {
|
||||
fail string
|
||||
completed bool
|
||||
}
|
||||
|
||||
func (s *FixtureCheckHelper) SetUpSuite(c *C) {
|
||||
switch s.fail {
|
||||
case "SetUpSuiteAssert":
|
||||
c.Assert(false, Equals, true)
|
||||
case "SetUpSuiteCheck":
|
||||
c.Check(false, Equals, true)
|
||||
}
|
||||
s.completed = true
|
||||
}
|
||||
|
||||
func (s *FixtureCheckHelper) SetUpTest(c *C) {
|
||||
switch s.fail {
|
||||
case "SetUpTestAssert":
|
||||
c.Assert(false, Equals, true)
|
||||
case "SetUpTestCheck":
|
||||
c.Check(false, Equals, true)
|
||||
}
|
||||
s.completed = true
|
||||
}
|
||||
|
||||
func (s *FixtureCheckHelper) Test(c *C) {
|
||||
// Do nothing.
|
||||
}
|
||||
|
||||
func (s *FixtureS) TestSetUpSuiteCheck(c *C) {
|
||||
helper := FixtureCheckHelper{fail: "SetUpSuiteCheck"}
|
||||
output := String{}
|
||||
Run(&helper, &RunConf{Output: &output})
|
||||
c.Assert(output.value, Matches,
|
||||
"\n---+\n"+
|
||||
"FAIL: fixture_test\\.go:[0-9]+: "+
|
||||
"FixtureCheckHelper\\.SetUpSuite\n\n"+
|
||||
"fixture_test\\.go:[0-9]+:\n"+
|
||||
" c\\.Check\\(false, Equals, true\\)\n"+
|
||||
"\\.+ obtained bool = false\n"+
|
||||
"\\.+ expected bool = true\n\n")
|
||||
c.Assert(helper.completed, Equals, true)
|
||||
}
|
||||
|
||||
func (s *FixtureS) TestSetUpSuiteAssert(c *C) {
|
||||
helper := FixtureCheckHelper{fail: "SetUpSuiteAssert"}
|
||||
output := String{}
|
||||
Run(&helper, &RunConf{Output: &output})
|
||||
c.Assert(output.value, Matches,
|
||||
"\n---+\n"+
|
||||
"FAIL: fixture_test\\.go:[0-9]+: "+
|
||||
"FixtureCheckHelper\\.SetUpSuite\n\n"+
|
||||
"fixture_test\\.go:[0-9]+:\n"+
|
||||
" c\\.Assert\\(false, Equals, true\\)\n"+
|
||||
"\\.+ obtained bool = false\n"+
|
||||
"\\.+ expected bool = true\n\n")
|
||||
c.Assert(helper.completed, Equals, false)
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Verify that logging within SetUpTest() persists within the test log itself.
|
||||
|
||||
type FixtureLogHelper struct {
|
||||
c *C
|
||||
}
|
||||
|
||||
func (s *FixtureLogHelper) SetUpTest(c *C) {
|
||||
s.c = c
|
||||
c.Log("1")
|
||||
}
|
||||
|
||||
func (s *FixtureLogHelper) Test(c *C) {
|
||||
c.Log("2")
|
||||
s.c.Log("3")
|
||||
c.Log("4")
|
||||
c.Fail()
|
||||
}
|
||||
|
||||
func (s *FixtureLogHelper) TearDownTest(c *C) {
|
||||
s.c.Log("5")
|
||||
}
|
||||
|
||||
func (s *FixtureS) TestFixtureLogging(c *C) {
|
||||
helper := FixtureLogHelper{}
|
||||
output := String{}
|
||||
Run(&helper, &RunConf{Output: &output})
|
||||
c.Assert(output.value, Matches,
|
||||
"\n---+\n"+
|
||||
"FAIL: fixture_test\\.go:[0-9]+: "+
|
||||
"FixtureLogHelper\\.Test\n\n"+
|
||||
"1\n2\n3\n4\n5\n")
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Skip() within fixture methods.
|
||||
|
||||
func (s *FixtureS) TestSkipSuite(c *C) {
|
||||
helper := FixtureHelper{skip: true, skipOnN: 0}
|
||||
output := String{}
|
||||
result := Run(&helper, &RunConf{Output: &output})
|
||||
c.Assert(output.value, Equals, "")
|
||||
c.Assert(helper.calls[0], Equals, "SetUpSuite")
|
||||
c.Assert(helper.calls[1], Equals, "TearDownSuite")
|
||||
c.Assert(len(helper.calls), Equals, 2)
|
||||
c.Assert(result.Skipped, Equals, 2)
|
||||
}
|
||||
|
||||
func (s *FixtureS) TestSkipTest(c *C) {
|
||||
helper := FixtureHelper{skip: true, skipOnN: 1}
|
||||
output := String{}
|
||||
result := Run(&helper, &RunConf{Output: &output})
|
||||
c.Assert(helper.calls[0], Equals, "SetUpSuite")
|
||||
c.Assert(helper.calls[1], Equals, "SetUpTest")
|
||||
c.Assert(helper.calls[2], Equals, "SetUpTest")
|
||||
c.Assert(helper.calls[3], Equals, "Test2")
|
||||
c.Assert(helper.calls[4], Equals, "TearDownTest")
|
||||
c.Assert(helper.calls[5], Equals, "TearDownSuite")
|
||||
c.Assert(len(helper.calls), Equals, 6)
|
||||
c.Assert(result.Skipped, Equals, 1)
|
||||
}
|
335
Godeps/_workspace/src/gopkg.in/check.v1/foundation_test.go
generated
vendored
335
Godeps/_workspace/src/gopkg.in/check.v1/foundation_test.go
generated
vendored
@ -1,335 +0,0 @@
|
||||
// These tests check that the foundations of gocheck are working properly.
|
||||
// They already assume that fundamental failing is working already, though,
|
||||
// since this was tested in bootstrap_test.go. Even then, some care may
|
||||
// still have to be taken when using external functions, since they should
|
||||
// of course not rely on functionality tested here.
|
||||
|
||||
package check_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"gopkg.in/check.v1"
|
||||
"log"
|
||||
"os"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Foundation test suite.
|
||||
|
||||
type FoundationS struct{}
|
||||
|
||||
var foundationS = check.Suite(&FoundationS{})
|
||||
|
||||
func (s *FoundationS) TestCountSuite(c *check.C) {
|
||||
suitesRun += 1
|
||||
}
|
||||
|
||||
func (s *FoundationS) TestErrorf(c *check.C) {
|
||||
// Do not use checkState() here. It depends on Errorf() working.
|
||||
expectedLog := fmt.Sprintf("foundation_test.go:%d:\n"+
|
||||
" c.Errorf(\"Error %%v!\", \"message\")\n"+
|
||||
"... Error: Error message!\n\n",
|
||||
getMyLine()+1)
|
||||
c.Errorf("Error %v!", "message")
|
||||
failed := c.Failed()
|
||||
c.Succeed()
|
||||
if log := c.GetTestLog(); log != expectedLog {
|
||||
c.Logf("Errorf() logged %#v rather than %#v", log, expectedLog)
|
||||
c.Fail()
|
||||
}
|
||||
if !failed {
|
||||
c.Logf("Errorf() didn't put the test in a failed state")
|
||||
c.Fail()
|
||||
}
|
||||
}
|
||||
|
||||
func (s *FoundationS) TestError(c *check.C) {
|
||||
expectedLog := fmt.Sprintf("foundation_test.go:%d:\n"+
|
||||
" c\\.Error\\(\"Error \", \"message!\"\\)\n"+
|
||||
"\\.\\.\\. Error: Error message!\n\n",
|
||||
getMyLine()+1)
|
||||
c.Error("Error ", "message!")
|
||||
checkState(c, nil,
|
||||
&expectedState{
|
||||
name: "Error(`Error `, `message!`)",
|
||||
failed: true,
|
||||
log: expectedLog,
|
||||
})
|
||||
}
|
||||
|
||||
func (s *FoundationS) TestFailNow(c *check.C) {
|
||||
defer (func() {
|
||||
if !c.Failed() {
|
||||
c.Error("FailNow() didn't fail the test")
|
||||
} else {
|
||||
c.Succeed()
|
||||
if c.GetTestLog() != "" {
|
||||
c.Error("Something got logged:\n" + c.GetTestLog())
|
||||
}
|
||||
}
|
||||
})()
|
||||
|
||||
c.FailNow()
|
||||
c.Log("FailNow() didn't stop the test")
|
||||
}
|
||||
|
||||
func (s *FoundationS) TestSucceedNow(c *check.C) {
|
||||
defer (func() {
|
||||
if c.Failed() {
|
||||
c.Error("SucceedNow() didn't succeed the test")
|
||||
}
|
||||
if c.GetTestLog() != "" {
|
||||
c.Error("Something got logged:\n" + c.GetTestLog())
|
||||
}
|
||||
})()
|
||||
|
||||
c.Fail()
|
||||
c.SucceedNow()
|
||||
c.Log("SucceedNow() didn't stop the test")
|
||||
}
|
||||
|
||||
func (s *FoundationS) TestFailureHeader(c *check.C) {
|
||||
output := String{}
|
||||
failHelper := FailHelper{}
|
||||
check.Run(&failHelper, &check.RunConf{Output: &output})
|
||||
header := fmt.Sprintf(""+
|
||||
"\n-----------------------------------"+
|
||||
"-----------------------------------\n"+
|
||||
"FAIL: check_test.go:%d: FailHelper.TestLogAndFail\n",
|
||||
failHelper.testLine)
|
||||
if strings.Index(output.value, header) == -1 {
|
||||
c.Errorf(""+
|
||||
"Failure didn't print a proper header.\n"+
|
||||
"... Got:\n%s... Expected something with:\n%s",
|
||||
output.value, header)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *FoundationS) TestFatal(c *check.C) {
|
||||
var line int
|
||||
defer (func() {
|
||||
if !c.Failed() {
|
||||
c.Error("Fatal() didn't fail the test")
|
||||
} else {
|
||||
c.Succeed()
|
||||
expected := fmt.Sprintf("foundation_test.go:%d:\n"+
|
||||
" c.Fatal(\"Die \", \"now!\")\n"+
|
||||
"... Error: Die now!\n\n",
|
||||
line)
|
||||
if c.GetTestLog() != expected {
|
||||
c.Error("Incorrect log:", c.GetTestLog())
|
||||
}
|
||||
}
|
||||
})()
|
||||
|
||||
line = getMyLine() + 1
|
||||
c.Fatal("Die ", "now!")
|
||||
c.Log("Fatal() didn't stop the test")
|
||||
}
|
||||
|
||||
func (s *FoundationS) TestFatalf(c *check.C) {
|
||||
var line int
|
||||
defer (func() {
|
||||
if !c.Failed() {
|
||||
c.Error("Fatalf() didn't fail the test")
|
||||
} else {
|
||||
c.Succeed()
|
||||
expected := fmt.Sprintf("foundation_test.go:%d:\n"+
|
||||
" c.Fatalf(\"Die %%s!\", \"now\")\n"+
|
||||
"... Error: Die now!\n\n",
|
||||
line)
|
||||
if c.GetTestLog() != expected {
|
||||
c.Error("Incorrect log:", c.GetTestLog())
|
||||
}
|
||||
}
|
||||
})()
|
||||
|
||||
line = getMyLine() + 1
|
||||
c.Fatalf("Die %s!", "now")
|
||||
c.Log("Fatalf() didn't stop the test")
|
||||
}
|
||||
|
||||
func (s *FoundationS) TestCallerLoggingInsideTest(c *check.C) {
|
||||
log := fmt.Sprintf(""+
|
||||
"foundation_test.go:%d:\n"+
|
||||
" result := c.Check\\(10, check.Equals, 20\\)\n"+
|
||||
"\\.\\.\\. obtained int = 10\n"+
|
||||
"\\.\\.\\. expected int = 20\n\n",
|
||||
getMyLine()+1)
|
||||
result := c.Check(10, check.Equals, 20)
|
||||
checkState(c, result,
|
||||
&expectedState{
|
||||
name: "Check(10, Equals, 20)",
|
||||
result: false,
|
||||
failed: true,
|
||||
log: log,
|
||||
})
|
||||
}
|
||||
|
||||
func (s *FoundationS) TestCallerLoggingInDifferentFile(c *check.C) {
|
||||
result, line := checkEqualWrapper(c, 10, 20)
|
||||
testLine := getMyLine() - 1
|
||||
log := fmt.Sprintf(""+
|
||||
"foundation_test.go:%d:\n"+
|
||||
" result, line := checkEqualWrapper\\(c, 10, 20\\)\n"+
|
||||
"check_test.go:%d:\n"+
|
||||
" return c.Check\\(obtained, check.Equals, expected\\), getMyLine\\(\\)\n"+
|
||||
"\\.\\.\\. obtained int = 10\n"+
|
||||
"\\.\\.\\. expected int = 20\n\n",
|
||||
testLine, line)
|
||||
checkState(c, result,
|
||||
&expectedState{
|
||||
name: "Check(10, Equals, 20)",
|
||||
result: false,
|
||||
failed: true,
|
||||
log: log,
|
||||
})
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// ExpectFailure() inverts the logic of failure.
|
||||
|
||||
type ExpectFailureSucceedHelper struct{}
|
||||
|
||||
func (s *ExpectFailureSucceedHelper) TestSucceed(c *check.C) {
|
||||
c.ExpectFailure("It booms!")
|
||||
c.Error("Boom!")
|
||||
}
|
||||
|
||||
type ExpectFailureFailHelper struct{}
|
||||
|
||||
func (s *ExpectFailureFailHelper) TestFail(c *check.C) {
|
||||
c.ExpectFailure("Bug #XYZ")
|
||||
}
|
||||
|
||||
func (s *FoundationS) TestExpectFailureFail(c *check.C) {
|
||||
helper := ExpectFailureFailHelper{}
|
||||
output := String{}
|
||||
result := check.Run(&helper, &check.RunConf{Output: &output})
|
||||
|
||||
expected := "" +
|
||||
"^\n-+\n" +
|
||||
"FAIL: foundation_test\\.go:[0-9]+:" +
|
||||
" ExpectFailureFailHelper\\.TestFail\n\n" +
|
||||
"\\.\\.\\. Error: Test succeeded, but was expected to fail\n" +
|
||||
"\\.\\.\\. Reason: Bug #XYZ\n$"
|
||||
|
||||
matched, err := regexp.MatchString(expected, output.value)
|
||||
if err != nil {
|
||||
c.Error("Bad expression: ", expected)
|
||||
} else if !matched {
|
||||
c.Error("ExpectFailure() didn't log properly:\n", output.value)
|
||||
}
|
||||
|
||||
c.Assert(result.ExpectedFailures, check.Equals, 0)
|
||||
}
|
||||
|
||||
func (s *FoundationS) TestExpectFailureSucceed(c *check.C) {
|
||||
helper := ExpectFailureSucceedHelper{}
|
||||
output := String{}
|
||||
result := check.Run(&helper, &check.RunConf{Output: &output})
|
||||
|
||||
c.Assert(output.value, check.Equals, "")
|
||||
c.Assert(result.ExpectedFailures, check.Equals, 1)
|
||||
}
|
||||
|
||||
func (s *FoundationS) TestExpectFailureSucceedVerbose(c *check.C) {
|
||||
helper := ExpectFailureSucceedHelper{}
|
||||
output := String{}
|
||||
result := check.Run(&helper, &check.RunConf{Output: &output, Verbose: true})
|
||||
|
||||
expected := "" +
|
||||
"FAIL EXPECTED: foundation_test\\.go:[0-9]+:" +
|
||||
" ExpectFailureSucceedHelper\\.TestSucceed \\(It booms!\\)\t *[.0-9]+s\n"
|
||||
|
||||
matched, err := regexp.MatchString(expected, output.value)
|
||||
if err != nil {
|
||||
c.Error("Bad expression: ", expected)
|
||||
} else if !matched {
|
||||
c.Error("ExpectFailure() didn't log properly:\n", output.value)
|
||||
}
|
||||
|
||||
c.Assert(result.ExpectedFailures, check.Equals, 1)
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Skip() allows stopping a test without positive/negative results.
|
||||
|
||||
type SkipTestHelper struct{}
|
||||
|
||||
func (s *SkipTestHelper) TestFail(c *check.C) {
|
||||
c.Skip("Wrong platform or whatever")
|
||||
c.Error("Boom!")
|
||||
}
|
||||
|
||||
func (s *FoundationS) TestSkip(c *check.C) {
|
||||
helper := SkipTestHelper{}
|
||||
output := String{}
|
||||
check.Run(&helper, &check.RunConf{Output: &output})
|
||||
|
||||
if output.value != "" {
|
||||
c.Error("Skip() logged something:\n", output.value)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *FoundationS) TestSkipVerbose(c *check.C) {
|
||||
helper := SkipTestHelper{}
|
||||
output := String{}
|
||||
check.Run(&helper, &check.RunConf{Output: &output, Verbose: true})
|
||||
|
||||
expected := "SKIP: foundation_test\\.go:[0-9]+: SkipTestHelper\\.TestFail" +
|
||||
" \\(Wrong platform or whatever\\)"
|
||||
matched, err := regexp.MatchString(expected, output.value)
|
||||
if err != nil {
|
||||
c.Error("Bad expression: ", expected)
|
||||
} else if !matched {
|
||||
c.Error("Skip() didn't log properly:\n", output.value)
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Check minimum *log.Logger interface provided by *check.C.
|
||||
|
||||
type minLogger interface {
|
||||
Output(calldepth int, s string) error
|
||||
}
|
||||
|
||||
func (s *BootstrapS) TestMinLogger(c *check.C) {
|
||||
var logger minLogger
|
||||
logger = log.New(os.Stderr, "", 0)
|
||||
logger = c
|
||||
logger.Output(0, "Hello there")
|
||||
expected := `\[LOG\] [0-9]+:[0-9][0-9]\.[0-9][0-9][0-9] +Hello there\n`
|
||||
output := c.GetTestLog()
|
||||
c.Assert(output, check.Matches, expected)
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Ensure that suites with embedded types are working fine, including the
|
||||
// the workaround for issue 906.
|
||||
|
||||
type EmbeddedInternalS struct {
|
||||
called bool
|
||||
}
|
||||
|
||||
type EmbeddedS struct {
|
||||
EmbeddedInternalS
|
||||
}
|
||||
|
||||
var embeddedS = check.Suite(&EmbeddedS{})
|
||||
|
||||
func (s *EmbeddedS) TestCountSuite(c *check.C) {
|
||||
suitesRun += 1
|
||||
}
|
||||
|
||||
func (s *EmbeddedInternalS) TestMethod(c *check.C) {
|
||||
c.Error("TestMethod() of the embedded type was called!?")
|
||||
}
|
||||
|
||||
func (s *EmbeddedS) TestMethod(c *check.C) {
|
||||
// http://code.google.com/p/go/issues/detail?id=906
|
||||
c.Check(s.called, check.Equals, false) // Go issue 906 is affecting the runner?
|
||||
s.called = true
|
||||
}
|
519
Godeps/_workspace/src/gopkg.in/check.v1/helpers_test.go
generated
vendored
519
Godeps/_workspace/src/gopkg.in/check.v1/helpers_test.go
generated
vendored
@ -1,519 +0,0 @@
|
||||
// These tests verify the inner workings of the helper methods associated
|
||||
// with check.T.
|
||||
|
||||
package check_test
|
||||
|
||||
import (
|
||||
"gopkg.in/check.v1"
|
||||
"os"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"sync"
|
||||
)
|
||||
|
||||
var helpersS = check.Suite(&HelpersS{})
|
||||
|
||||
type HelpersS struct{}
|
||||
|
||||
func (s *HelpersS) TestCountSuite(c *check.C) {
|
||||
suitesRun += 1
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Fake checker and bug info to verify the behavior of Assert() and Check().
|
||||
|
||||
type MyChecker struct {
|
||||
info *check.CheckerInfo
|
||||
params []interface{}
|
||||
names []string
|
||||
result bool
|
||||
error string
|
||||
}
|
||||
|
||||
func (checker *MyChecker) Info() *check.CheckerInfo {
|
||||
if checker.info == nil {
|
||||
return &check.CheckerInfo{Name: "MyChecker", Params: []string{"myobtained", "myexpected"}}
|
||||
}
|
||||
return checker.info
|
||||
}
|
||||
|
||||
func (checker *MyChecker) Check(params []interface{}, names []string) (bool, string) {
|
||||
rparams := checker.params
|
||||
rnames := checker.names
|
||||
checker.params = append([]interface{}{}, params...)
|
||||
checker.names = append([]string{}, names...)
|
||||
if rparams != nil {
|
||||
copy(params, rparams)
|
||||
}
|
||||
if rnames != nil {
|
||||
copy(names, rnames)
|
||||
}
|
||||
return checker.result, checker.error
|
||||
}
|
||||
|
||||
type myCommentType string
|
||||
|
||||
func (c myCommentType) CheckCommentString() string {
|
||||
return string(c)
|
||||
}
|
||||
|
||||
func myComment(s string) myCommentType {
|
||||
return myCommentType(s)
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Ensure a real checker actually works fine.
|
||||
|
||||
func (s *HelpersS) TestCheckerInterface(c *check.C) {
|
||||
testHelperSuccess(c, "Check(1, Equals, 1)", true, func() interface{} {
|
||||
return c.Check(1, check.Equals, 1)
|
||||
})
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Tests for Check(), mostly the same as for Assert() following these.
|
||||
|
||||
func (s *HelpersS) TestCheckSucceedWithExpected(c *check.C) {
|
||||
checker := &MyChecker{result: true}
|
||||
testHelperSuccess(c, "Check(1, checker, 2)", true, func() interface{} {
|
||||
return c.Check(1, checker, 2)
|
||||
})
|
||||
if !reflect.DeepEqual(checker.params, []interface{}{1, 2}) {
|
||||
c.Fatalf("Bad params for check: %#v", checker.params)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *HelpersS) TestCheckSucceedWithoutExpected(c *check.C) {
|
||||
checker := &MyChecker{result: true, info: &check.CheckerInfo{Params: []string{"myvalue"}}}
|
||||
testHelperSuccess(c, "Check(1, checker)", true, func() interface{} {
|
||||
return c.Check(1, checker)
|
||||
})
|
||||
if !reflect.DeepEqual(checker.params, []interface{}{1}) {
|
||||
c.Fatalf("Bad params for check: %#v", checker.params)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *HelpersS) TestCheckFailWithExpected(c *check.C) {
|
||||
checker := &MyChecker{result: false}
|
||||
log := "(?s)helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" +
|
||||
" return c\\.Check\\(1, checker, 2\\)\n" +
|
||||
"\\.+ myobtained int = 1\n" +
|
||||
"\\.+ myexpected int = 2\n\n"
|
||||
testHelperFailure(c, "Check(1, checker, 2)", false, false, log,
|
||||
func() interface{} {
|
||||
return c.Check(1, checker, 2)
|
||||
})
|
||||
}
|
||||
|
||||
func (s *HelpersS) TestCheckFailWithExpectedAndComment(c *check.C) {
|
||||
checker := &MyChecker{result: false}
|
||||
log := "(?s)helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" +
|
||||
" return c\\.Check\\(1, checker, 2, myComment\\(\"Hello world!\"\\)\\)\n" +
|
||||
"\\.+ myobtained int = 1\n" +
|
||||
"\\.+ myexpected int = 2\n" +
|
||||
"\\.+ Hello world!\n\n"
|
||||
testHelperFailure(c, "Check(1, checker, 2, msg)", false, false, log,
|
||||
func() interface{} {
|
||||
return c.Check(1, checker, 2, myComment("Hello world!"))
|
||||
})
|
||||
}
|
||||
|
||||
func (s *HelpersS) TestCheckFailWithExpectedAndStaticComment(c *check.C) {
|
||||
checker := &MyChecker{result: false}
|
||||
log := "(?s)helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" +
|
||||
" // Nice leading comment\\.\n" +
|
||||
" return c\\.Check\\(1, checker, 2\\) // Hello there\n" +
|
||||
"\\.+ myobtained int = 1\n" +
|
||||
"\\.+ myexpected int = 2\n\n"
|
||||
testHelperFailure(c, "Check(1, checker, 2, msg)", false, false, log,
|
||||
func() interface{} {
|
||||
// Nice leading comment.
|
||||
return c.Check(1, checker, 2) // Hello there
|
||||
})
|
||||
}
|
||||
|
||||
func (s *HelpersS) TestCheckFailWithoutExpected(c *check.C) {
|
||||
checker := &MyChecker{result: false, info: &check.CheckerInfo{Params: []string{"myvalue"}}}
|
||||
log := "(?s)helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" +
|
||||
" return c\\.Check\\(1, checker\\)\n" +
|
||||
"\\.+ myvalue int = 1\n\n"
|
||||
testHelperFailure(c, "Check(1, checker)", false, false, log,
|
||||
func() interface{} {
|
||||
return c.Check(1, checker)
|
||||
})
|
||||
}
|
||||
|
||||
func (s *HelpersS) TestCheckFailWithoutExpectedAndMessage(c *check.C) {
|
||||
checker := &MyChecker{result: false, info: &check.CheckerInfo{Params: []string{"myvalue"}}}
|
||||
log := "(?s)helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" +
|
||||
" return c\\.Check\\(1, checker, myComment\\(\"Hello world!\"\\)\\)\n" +
|
||||
"\\.+ myvalue int = 1\n" +
|
||||
"\\.+ Hello world!\n\n"
|
||||
testHelperFailure(c, "Check(1, checker, msg)", false, false, log,
|
||||
func() interface{} {
|
||||
return c.Check(1, checker, myComment("Hello world!"))
|
||||
})
|
||||
}
|
||||
|
||||
func (s *HelpersS) TestCheckWithMissingExpected(c *check.C) {
|
||||
checker := &MyChecker{result: true}
|
||||
log := "(?s)helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" +
|
||||
" return c\\.Check\\(1, checker\\)\n" +
|
||||
"\\.+ Check\\(myobtained, MyChecker, myexpected\\):\n" +
|
||||
"\\.+ Wrong number of parameters for MyChecker: " +
|
||||
"want 3, got 2\n\n"
|
||||
testHelperFailure(c, "Check(1, checker, !?)", false, false, log,
|
||||
func() interface{} {
|
||||
return c.Check(1, checker)
|
||||
})
|
||||
}
|
||||
|
||||
func (s *HelpersS) TestCheckWithTooManyExpected(c *check.C) {
|
||||
checker := &MyChecker{result: true}
|
||||
log := "(?s)helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" +
|
||||
" return c\\.Check\\(1, checker, 2, 3\\)\n" +
|
||||
"\\.+ Check\\(myobtained, MyChecker, myexpected\\):\n" +
|
||||
"\\.+ Wrong number of parameters for MyChecker: " +
|
||||
"want 3, got 4\n\n"
|
||||
testHelperFailure(c, "Check(1, checker, 2, 3)", false, false, log,
|
||||
func() interface{} {
|
||||
return c.Check(1, checker, 2, 3)
|
||||
})
|
||||
}
|
||||
|
||||
func (s *HelpersS) TestCheckWithError(c *check.C) {
|
||||
checker := &MyChecker{result: false, error: "Some not so cool data provided!"}
|
||||
log := "(?s)helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" +
|
||||
" return c\\.Check\\(1, checker, 2\\)\n" +
|
||||
"\\.+ myobtained int = 1\n" +
|
||||
"\\.+ myexpected int = 2\n" +
|
||||
"\\.+ Some not so cool data provided!\n\n"
|
||||
testHelperFailure(c, "Check(1, checker, 2)", false, false, log,
|
||||
func() interface{} {
|
||||
return c.Check(1, checker, 2)
|
||||
})
|
||||
}
|
||||
|
||||
func (s *HelpersS) TestCheckWithNilChecker(c *check.C) {
|
||||
log := "(?s)helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" +
|
||||
" return c\\.Check\\(1, nil\\)\n" +
|
||||
"\\.+ Check\\(obtained, nil!\\?, \\.\\.\\.\\):\n" +
|
||||
"\\.+ Oops\\.\\. you've provided a nil checker!\n\n"
|
||||
testHelperFailure(c, "Check(obtained, nil)", false, false, log,
|
||||
func() interface{} {
|
||||
return c.Check(1, nil)
|
||||
})
|
||||
}
|
||||
|
||||
func (s *HelpersS) TestCheckWithParamsAndNamesMutation(c *check.C) {
|
||||
checker := &MyChecker{result: false, params: []interface{}{3, 4}, names: []string{"newobtained", "newexpected"}}
|
||||
log := "(?s)helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" +
|
||||
" return c\\.Check\\(1, checker, 2\\)\n" +
|
||||
"\\.+ newobtained int = 3\n" +
|
||||
"\\.+ newexpected int = 4\n\n"
|
||||
testHelperFailure(c, "Check(1, checker, 2) with mutation", false, false, log,
|
||||
func() interface{} {
|
||||
return c.Check(1, checker, 2)
|
||||
})
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Tests for Assert(), mostly the same as for Check() above.
|
||||
|
||||
func (s *HelpersS) TestAssertSucceedWithExpected(c *check.C) {
|
||||
checker := &MyChecker{result: true}
|
||||
testHelperSuccess(c, "Assert(1, checker, 2)", nil, func() interface{} {
|
||||
c.Assert(1, checker, 2)
|
||||
return nil
|
||||
})
|
||||
if !reflect.DeepEqual(checker.params, []interface{}{1, 2}) {
|
||||
c.Fatalf("Bad params for check: %#v", checker.params)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *HelpersS) TestAssertSucceedWithoutExpected(c *check.C) {
|
||||
checker := &MyChecker{result: true, info: &check.CheckerInfo{Params: []string{"myvalue"}}}
|
||||
testHelperSuccess(c, "Assert(1, checker)", nil, func() interface{} {
|
||||
c.Assert(1, checker)
|
||||
return nil
|
||||
})
|
||||
if !reflect.DeepEqual(checker.params, []interface{}{1}) {
|
||||
c.Fatalf("Bad params for check: %#v", checker.params)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *HelpersS) TestAssertFailWithExpected(c *check.C) {
|
||||
checker := &MyChecker{result: false}
|
||||
log := "(?s)helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" +
|
||||
" c\\.Assert\\(1, checker, 2\\)\n" +
|
||||
"\\.+ myobtained int = 1\n" +
|
||||
"\\.+ myexpected int = 2\n\n"
|
||||
testHelperFailure(c, "Assert(1, checker, 2)", nil, true, log,
|
||||
func() interface{} {
|
||||
c.Assert(1, checker, 2)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func (s *HelpersS) TestAssertFailWithExpectedAndMessage(c *check.C) {
|
||||
checker := &MyChecker{result: false}
|
||||
log := "(?s)helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" +
|
||||
" c\\.Assert\\(1, checker, 2, myComment\\(\"Hello world!\"\\)\\)\n" +
|
||||
"\\.+ myobtained int = 1\n" +
|
||||
"\\.+ myexpected int = 2\n" +
|
||||
"\\.+ Hello world!\n\n"
|
||||
testHelperFailure(c, "Assert(1, checker, 2, msg)", nil, true, log,
|
||||
func() interface{} {
|
||||
c.Assert(1, checker, 2, myComment("Hello world!"))
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func (s *HelpersS) TestAssertFailWithoutExpected(c *check.C) {
|
||||
checker := &MyChecker{result: false, info: &check.CheckerInfo{Params: []string{"myvalue"}}}
|
||||
log := "(?s)helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" +
|
||||
" c\\.Assert\\(1, checker\\)\n" +
|
||||
"\\.+ myvalue int = 1\n\n"
|
||||
testHelperFailure(c, "Assert(1, checker)", nil, true, log,
|
||||
func() interface{} {
|
||||
c.Assert(1, checker)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func (s *HelpersS) TestAssertFailWithoutExpectedAndMessage(c *check.C) {
|
||||
checker := &MyChecker{result: false, info: &check.CheckerInfo{Params: []string{"myvalue"}}}
|
||||
log := "(?s)helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" +
|
||||
" c\\.Assert\\(1, checker, myComment\\(\"Hello world!\"\\)\\)\n" +
|
||||
"\\.+ myvalue int = 1\n" +
|
||||
"\\.+ Hello world!\n\n"
|
||||
testHelperFailure(c, "Assert(1, checker, msg)", nil, true, log,
|
||||
func() interface{} {
|
||||
c.Assert(1, checker, myComment("Hello world!"))
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func (s *HelpersS) TestAssertWithMissingExpected(c *check.C) {
|
||||
checker := &MyChecker{result: true}
|
||||
log := "(?s)helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" +
|
||||
" c\\.Assert\\(1, checker\\)\n" +
|
||||
"\\.+ Assert\\(myobtained, MyChecker, myexpected\\):\n" +
|
||||
"\\.+ Wrong number of parameters for MyChecker: " +
|
||||
"want 3, got 2\n\n"
|
||||
testHelperFailure(c, "Assert(1, checker, !?)", nil, true, log,
|
||||
func() interface{} {
|
||||
c.Assert(1, checker)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func (s *HelpersS) TestAssertWithError(c *check.C) {
|
||||
checker := &MyChecker{result: false, error: "Some not so cool data provided!"}
|
||||
log := "(?s)helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" +
|
||||
" c\\.Assert\\(1, checker, 2\\)\n" +
|
||||
"\\.+ myobtained int = 1\n" +
|
||||
"\\.+ myexpected int = 2\n" +
|
||||
"\\.+ Some not so cool data provided!\n\n"
|
||||
testHelperFailure(c, "Assert(1, checker, 2)", nil, true, log,
|
||||
func() interface{} {
|
||||
c.Assert(1, checker, 2)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func (s *HelpersS) TestAssertWithNilChecker(c *check.C) {
|
||||
log := "(?s)helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" +
|
||||
" c\\.Assert\\(1, nil\\)\n" +
|
||||
"\\.+ Assert\\(obtained, nil!\\?, \\.\\.\\.\\):\n" +
|
||||
"\\.+ Oops\\.\\. you've provided a nil checker!\n\n"
|
||||
testHelperFailure(c, "Assert(obtained, nil)", nil, true, log,
|
||||
func() interface{} {
|
||||
c.Assert(1, nil)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Ensure that values logged work properly in some interesting cases.
|
||||
|
||||
func (s *HelpersS) TestValueLoggingWithArrays(c *check.C) {
|
||||
checker := &MyChecker{result: false}
|
||||
log := "(?s)helpers_test.go:[0-9]+:.*\nhelpers_test.go:[0-9]+:\n" +
|
||||
" return c\\.Check\\(\\[\\]byte{1, 2}, checker, \\[\\]byte{1, 3}\\)\n" +
|
||||
"\\.+ myobtained \\[\\]uint8 = \\[\\]byte{0x1, 0x2}\n" +
|
||||
"\\.+ myexpected \\[\\]uint8 = \\[\\]byte{0x1, 0x3}\n\n"
|
||||
testHelperFailure(c, "Check([]byte{1}, chk, []byte{3})", false, false, log,
|
||||
func() interface{} {
|
||||
return c.Check([]byte{1, 2}, checker, []byte{1, 3})
|
||||
})
|
||||
}
|
||||
|
||||
func (s *HelpersS) TestValueLoggingWithMultiLine(c *check.C) {
|
||||
checker := &MyChecker{result: false}
|
||||
log := "(?s)helpers_test.go:[0-9]+:.*\nhelpers_test.go:[0-9]+:\n" +
|
||||
" return c\\.Check\\(\"a\\\\nb\\\\n\", checker, \"a\\\\nb\\\\nc\"\\)\n" +
|
||||
"\\.+ myobtained string = \"\" \\+\n" +
|
||||
"\\.+ \"a\\\\n\" \\+\n" +
|
||||
"\\.+ \"b\\\\n\"\n" +
|
||||
"\\.+ myexpected string = \"\" \\+\n" +
|
||||
"\\.+ \"a\\\\n\" \\+\n" +
|
||||
"\\.+ \"b\\\\n\" \\+\n" +
|
||||
"\\.+ \"c\"\n\n"
|
||||
testHelperFailure(c, `Check("a\nb\n", chk, "a\nb\nc")`, false, false, log,
|
||||
func() interface{} {
|
||||
return c.Check("a\nb\n", checker, "a\nb\nc")
|
||||
})
|
||||
}
|
||||
|
||||
func (s *HelpersS) TestValueLoggingWithMultiLineException(c *check.C) {
|
||||
// If the newline is at the end of the string, don't log as multi-line.
|
||||
checker := &MyChecker{result: false}
|
||||
log := "(?s)helpers_test.go:[0-9]+:.*\nhelpers_test.go:[0-9]+:\n" +
|
||||
" return c\\.Check\\(\"a b\\\\n\", checker, \"a\\\\nb\"\\)\n" +
|
||||
"\\.+ myobtained string = \"a b\\\\n\"\n" +
|
||||
"\\.+ myexpected string = \"\" \\+\n" +
|
||||
"\\.+ \"a\\\\n\" \\+\n" +
|
||||
"\\.+ \"b\"\n\n"
|
||||
testHelperFailure(c, `Check("a b\n", chk, "a\nb")`, false, false, log,
|
||||
func() interface{} {
|
||||
return c.Check("a b\n", checker, "a\nb")
|
||||
})
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// MakeDir() tests.
|
||||
|
||||
type MkDirHelper struct {
|
||||
path1 string
|
||||
path2 string
|
||||
isDir1 bool
|
||||
isDir2 bool
|
||||
isDir3 bool
|
||||
isDir4 bool
|
||||
}
|
||||
|
||||
func (s *MkDirHelper) SetUpSuite(c *check.C) {
|
||||
s.path1 = c.MkDir()
|
||||
s.isDir1 = isDir(s.path1)
|
||||
}
|
||||
|
||||
func (s *MkDirHelper) Test(c *check.C) {
|
||||
s.path2 = c.MkDir()
|
||||
s.isDir2 = isDir(s.path2)
|
||||
}
|
||||
|
||||
func (s *MkDirHelper) TearDownSuite(c *check.C) {
|
||||
s.isDir3 = isDir(s.path1)
|
||||
s.isDir4 = isDir(s.path2)
|
||||
}
|
||||
|
||||
func (s *HelpersS) TestMkDir(c *check.C) {
|
||||
helper := MkDirHelper{}
|
||||
output := String{}
|
||||
check.Run(&helper, &check.RunConf{Output: &output})
|
||||
c.Assert(output.value, check.Equals, "")
|
||||
c.Check(helper.isDir1, check.Equals, true)
|
||||
c.Check(helper.isDir2, check.Equals, true)
|
||||
c.Check(helper.isDir3, check.Equals, true)
|
||||
c.Check(helper.isDir4, check.Equals, true)
|
||||
c.Check(helper.path1, check.Not(check.Equals),
|
||||
helper.path2)
|
||||
c.Check(isDir(helper.path1), check.Equals, false)
|
||||
c.Check(isDir(helper.path2), check.Equals, false)
|
||||
}
|
||||
|
||||
func isDir(path string) bool {
|
||||
if stat, err := os.Stat(path); err == nil {
|
||||
return stat.IsDir()
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Concurrent logging should not corrupt the underling buffer.
|
||||
// Use go test -race to detect the race in this test.
|
||||
func (s *HelpersS) TestConcurrentLogging(c *check.C) {
|
||||
defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(runtime.NumCPU()))
|
||||
var start, stop sync.WaitGroup
|
||||
start.Add(1)
|
||||
for i, n := 0, runtime.NumCPU()*2; i < n; i++ {
|
||||
stop.Add(1)
|
||||
go func(i int) {
|
||||
start.Wait()
|
||||
for j := 0; j < 30; j++ {
|
||||
c.Logf("Worker %d: line %d", i, j)
|
||||
}
|
||||
stop.Done()
|
||||
}(i)
|
||||
}
|
||||
start.Done()
|
||||
stop.Wait()
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Test the TestName function
|
||||
|
||||
type TestNameHelper struct {
|
||||
name1 string
|
||||
name2 string
|
||||
name3 string
|
||||
name4 string
|
||||
name5 string
|
||||
}
|
||||
|
||||
func (s *TestNameHelper) SetUpSuite(c *check.C) { s.name1 = c.TestName() }
|
||||
func (s *TestNameHelper) SetUpTest(c *check.C) { s.name2 = c.TestName() }
|
||||
func (s *TestNameHelper) Test(c *check.C) { s.name3 = c.TestName() }
|
||||
func (s *TestNameHelper) TearDownTest(c *check.C) { s.name4 = c.TestName() }
|
||||
func (s *TestNameHelper) TearDownSuite(c *check.C) { s.name5 = c.TestName() }
|
||||
|
||||
func (s *HelpersS) TestTestName(c *check.C) {
|
||||
helper := TestNameHelper{}
|
||||
output := String{}
|
||||
check.Run(&helper, &check.RunConf{Output: &output})
|
||||
c.Check(helper.name1, check.Equals, "")
|
||||
c.Check(helper.name2, check.Equals, "TestNameHelper.Test")
|
||||
c.Check(helper.name3, check.Equals, "TestNameHelper.Test")
|
||||
c.Check(helper.name4, check.Equals, "TestNameHelper.Test")
|
||||
c.Check(helper.name5, check.Equals, "")
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// A couple of helper functions to test helper functions. :-)
|
||||
|
||||
func testHelperSuccess(c *check.C, name string, expectedResult interface{}, closure func() interface{}) {
|
||||
var result interface{}
|
||||
defer (func() {
|
||||
if err := recover(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
checkState(c, result,
|
||||
&expectedState{
|
||||
name: name,
|
||||
result: expectedResult,
|
||||
failed: false,
|
||||
log: "",
|
||||
})
|
||||
})()
|
||||
result = closure()
|
||||
}
|
||||
|
||||
func testHelperFailure(c *check.C, name string, expectedResult interface{}, shouldStop bool, log string, closure func() interface{}) {
|
||||
var result interface{}
|
||||
defer (func() {
|
||||
if err := recover(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
checkState(c, result,
|
||||
&expectedState{
|
||||
name: name,
|
||||
result: expectedResult,
|
||||
failed: true,
|
||||
log: log,
|
||||
})
|
||||
})()
|
||||
result = closure()
|
||||
if shouldStop {
|
||||
c.Logf("%s didn't stop when it should", name)
|
||||
}
|
||||
}
|
104
Godeps/_workspace/src/gopkg.in/check.v1/printer_test.go
generated
vendored
104
Godeps/_workspace/src/gopkg.in/check.v1/printer_test.go
generated
vendored
@ -1,104 +0,0 @@
|
||||
package check_test
|
||||
|
||||
import (
|
||||
. "gopkg.in/check.v1"
|
||||
)
|
||||
|
||||
var _ = Suite(&PrinterS{})
|
||||
|
||||
type PrinterS struct{}
|
||||
|
||||
func (s *PrinterS) TestCountSuite(c *C) {
|
||||
suitesRun += 1
|
||||
}
|
||||
|
||||
var printTestFuncLine int
|
||||
|
||||
func init() {
|
||||
printTestFuncLine = getMyLine() + 3
|
||||
}
|
||||
|
||||
func printTestFunc() {
|
||||
println(1) // Comment1
|
||||
if 2 == 2 { // Comment2
|
||||
println(3) // Comment3
|
||||
}
|
||||
switch 5 {
|
||||
case 6: println(6) // Comment6
|
||||
println(7)
|
||||
}
|
||||
switch interface{}(9).(type) {// Comment9
|
||||
case int: println(10)
|
||||
println(11)
|
||||
}
|
||||
select {
|
||||
case <-(chan bool)(nil): println(14)
|
||||
println(15)
|
||||
default: println(16)
|
||||
println(17)
|
||||
}
|
||||
println(19,
|
||||
20)
|
||||
_ = func() { println(21)
|
||||
println(22)
|
||||
}
|
||||
println(24, func() {
|
||||
println(25)
|
||||
})
|
||||
// Leading comment
|
||||
// with multiple lines.
|
||||
println(29) // Comment29
|
||||
}
|
||||
|
||||
var printLineTests = []struct {
|
||||
line int
|
||||
output string
|
||||
}{
|
||||
{1, "println(1) // Comment1"},
|
||||
{2, "if 2 == 2 { // Comment2\n ...\n}"},
|
||||
{3, "println(3) // Comment3"},
|
||||
{5, "switch 5 {\n...\n}"},
|
||||
{6, "case 6:\n println(6) // Comment6\n ..."},
|
||||
{7, "println(7)"},
|
||||
{9, "switch interface{}(9).(type) { // Comment9\n...\n}"},
|
||||
{10, "case int:\n println(10)\n ..."},
|
||||
{14, "case <-(chan bool)(nil):\n println(14)\n ..."},
|
||||
{15, "println(15)"},
|
||||
{16, "default:\n println(16)\n ..."},
|
||||
{17, "println(17)"},
|
||||
{19, "println(19,\n 20)"},
|
||||
{20, "println(19,\n 20)"},
|
||||
{21, "_ = func() {\n println(21)\n println(22)\n}"},
|
||||
{22, "println(22)"},
|
||||
{24, "println(24, func() {\n println(25)\n})"},
|
||||
{25, "println(25)"},
|
||||
{26, "println(24, func() {\n println(25)\n})"},
|
||||
{29, "// Leading comment\n// with multiple lines.\nprintln(29) // Comment29"},
|
||||
}
|
||||
|
||||
func (s *PrinterS) TestPrintLine(c *C) {
|
||||
for _, test := range printLineTests {
|
||||
output, err := PrintLine("printer_test.go", printTestFuncLine+test.line)
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(output, Equals, test.output)
|
||||
}
|
||||
}
|
||||
|
||||
var indentTests = []struct {
|
||||
in, out string
|
||||
}{
|
||||
{"", ""},
|
||||
{"\n", "\n"},
|
||||
{"a", ">>>a"},
|
||||
{"a\n", ">>>a\n"},
|
||||
{"a\nb", ">>>a\n>>>b"},
|
||||
{" ", ">>> "},
|
||||
}
|
||||
|
||||
func (s *PrinterS) TestIndent(c *C) {
|
||||
for _, test := range indentTests {
|
||||
out := Indent(test.in, ">>>")
|
||||
c.Assert(out, Equals, test.out)
|
||||
}
|
||||
|
||||
}
|
419
Godeps/_workspace/src/gopkg.in/check.v1/run_test.go
generated
vendored
419
Godeps/_workspace/src/gopkg.in/check.v1/run_test.go
generated
vendored
@ -1,419 +0,0 @@
|
||||
// These tests verify the test running logic.
|
||||
|
||||
package check_test
|
||||
|
||||
import (
|
||||
"errors"
|
||||
. "gopkg.in/check.v1"
|
||||
"os"
|
||||
"sync"
|
||||
)
|
||||
|
||||
var runnerS = Suite(&RunS{})
|
||||
|
||||
type RunS struct{}
|
||||
|
||||
func (s *RunS) TestCountSuite(c *C) {
|
||||
suitesRun += 1
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Tests ensuring result counting works properly.
|
||||
|
||||
func (s *RunS) TestSuccess(c *C) {
|
||||
output := String{}
|
||||
result := Run(&SuccessHelper{}, &RunConf{Output: &output})
|
||||
c.Check(result.Succeeded, Equals, 1)
|
||||
c.Check(result.Failed, Equals, 0)
|
||||
c.Check(result.Skipped, Equals, 0)
|
||||
c.Check(result.Panicked, Equals, 0)
|
||||
c.Check(result.FixturePanicked, Equals, 0)
|
||||
c.Check(result.Missed, Equals, 0)
|
||||
c.Check(result.RunError, IsNil)
|
||||
}
|
||||
|
||||
func (s *RunS) TestFailure(c *C) {
|
||||
output := String{}
|
||||
result := Run(&FailHelper{}, &RunConf{Output: &output})
|
||||
c.Check(result.Succeeded, Equals, 0)
|
||||
c.Check(result.Failed, Equals, 1)
|
||||
c.Check(result.Skipped, Equals, 0)
|
||||
c.Check(result.Panicked, Equals, 0)
|
||||
c.Check(result.FixturePanicked, Equals, 0)
|
||||
c.Check(result.Missed, Equals, 0)
|
||||
c.Check(result.RunError, IsNil)
|
||||
}
|
||||
|
||||
func (s *RunS) TestFixture(c *C) {
|
||||
output := String{}
|
||||
result := Run(&FixtureHelper{}, &RunConf{Output: &output})
|
||||
c.Check(result.Succeeded, Equals, 2)
|
||||
c.Check(result.Failed, Equals, 0)
|
||||
c.Check(result.Skipped, Equals, 0)
|
||||
c.Check(result.Panicked, Equals, 0)
|
||||
c.Check(result.FixturePanicked, Equals, 0)
|
||||
c.Check(result.Missed, Equals, 0)
|
||||
c.Check(result.RunError, IsNil)
|
||||
}
|
||||
|
||||
func (s *RunS) TestPanicOnTest(c *C) {
|
||||
output := String{}
|
||||
helper := &FixtureHelper{panicOn: "Test1"}
|
||||
result := Run(helper, &RunConf{Output: &output})
|
||||
c.Check(result.Succeeded, Equals, 1)
|
||||
c.Check(result.Failed, Equals, 0)
|
||||
c.Check(result.Skipped, Equals, 0)
|
||||
c.Check(result.Panicked, Equals, 1)
|
||||
c.Check(result.FixturePanicked, Equals, 0)
|
||||
c.Check(result.Missed, Equals, 0)
|
||||
c.Check(result.RunError, IsNil)
|
||||
}
|
||||
|
||||
func (s *RunS) TestPanicOnSetUpTest(c *C) {
|
||||
output := String{}
|
||||
helper := &FixtureHelper{panicOn: "SetUpTest"}
|
||||
result := Run(helper, &RunConf{Output: &output})
|
||||
c.Check(result.Succeeded, Equals, 0)
|
||||
c.Check(result.Failed, Equals, 0)
|
||||
c.Check(result.Skipped, Equals, 0)
|
||||
c.Check(result.Panicked, Equals, 0)
|
||||
c.Check(result.FixturePanicked, Equals, 1)
|
||||
c.Check(result.Missed, Equals, 2)
|
||||
c.Check(result.RunError, IsNil)
|
||||
}
|
||||
|
||||
func (s *RunS) TestPanicOnSetUpSuite(c *C) {
|
||||
output := String{}
|
||||
helper := &FixtureHelper{panicOn: "SetUpSuite"}
|
||||
result := Run(helper, &RunConf{Output: &output})
|
||||
c.Check(result.Succeeded, Equals, 0)
|
||||
c.Check(result.Failed, Equals, 0)
|
||||
c.Check(result.Skipped, Equals, 0)
|
||||
c.Check(result.Panicked, Equals, 0)
|
||||
c.Check(result.FixturePanicked, Equals, 1)
|
||||
c.Check(result.Missed, Equals, 2)
|
||||
c.Check(result.RunError, IsNil)
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Check result aggregation.
|
||||
|
||||
func (s *RunS) TestAdd(c *C) {
|
||||
result := &Result{
|
||||
Succeeded: 1,
|
||||
Skipped: 2,
|
||||
Failed: 3,
|
||||
Panicked: 4,
|
||||
FixturePanicked: 5,
|
||||
Missed: 6,
|
||||
ExpectedFailures: 7,
|
||||
}
|
||||
result.Add(&Result{
|
||||
Succeeded: 10,
|
||||
Skipped: 20,
|
||||
Failed: 30,
|
||||
Panicked: 40,
|
||||
FixturePanicked: 50,
|
||||
Missed: 60,
|
||||
ExpectedFailures: 70,
|
||||
})
|
||||
c.Check(result.Succeeded, Equals, 11)
|
||||
c.Check(result.Skipped, Equals, 22)
|
||||
c.Check(result.Failed, Equals, 33)
|
||||
c.Check(result.Panicked, Equals, 44)
|
||||
c.Check(result.FixturePanicked, Equals, 55)
|
||||
c.Check(result.Missed, Equals, 66)
|
||||
c.Check(result.ExpectedFailures, Equals, 77)
|
||||
c.Check(result.RunError, IsNil)
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Check the Passed() method.
|
||||
|
||||
func (s *RunS) TestPassed(c *C) {
|
||||
c.Assert((&Result{}).Passed(), Equals, true)
|
||||
c.Assert((&Result{Succeeded: 1}).Passed(), Equals, true)
|
||||
c.Assert((&Result{Skipped: 1}).Passed(), Equals, true)
|
||||
c.Assert((&Result{Failed: 1}).Passed(), Equals, false)
|
||||
c.Assert((&Result{Panicked: 1}).Passed(), Equals, false)
|
||||
c.Assert((&Result{FixturePanicked: 1}).Passed(), Equals, false)
|
||||
c.Assert((&Result{Missed: 1}).Passed(), Equals, false)
|
||||
c.Assert((&Result{RunError: errors.New("!")}).Passed(), Equals, false)
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Check that result printing is working correctly.
|
||||
|
||||
func (s *RunS) TestPrintSuccess(c *C) {
|
||||
result := &Result{Succeeded: 5}
|
||||
c.Check(result.String(), Equals, "OK: 5 passed")
|
||||
}
|
||||
|
||||
func (s *RunS) TestPrintFailure(c *C) {
|
||||
result := &Result{Failed: 5}
|
||||
c.Check(result.String(), Equals, "OOPS: 0 passed, 5 FAILED")
|
||||
}
|
||||
|
||||
func (s *RunS) TestPrintSkipped(c *C) {
|
||||
result := &Result{Skipped: 5}
|
||||
c.Check(result.String(), Equals, "OK: 0 passed, 5 skipped")
|
||||
}
|
||||
|
||||
func (s *RunS) TestPrintExpectedFailures(c *C) {
|
||||
result := &Result{ExpectedFailures: 5}
|
||||
c.Check(result.String(), Equals, "OK: 0 passed, 5 expected failures")
|
||||
}
|
||||
|
||||
func (s *RunS) TestPrintPanicked(c *C) {
|
||||
result := &Result{Panicked: 5}
|
||||
c.Check(result.String(), Equals, "OOPS: 0 passed, 5 PANICKED")
|
||||
}
|
||||
|
||||
func (s *RunS) TestPrintFixturePanicked(c *C) {
|
||||
result := &Result{FixturePanicked: 5}
|
||||
c.Check(result.String(), Equals, "OOPS: 0 passed, 5 FIXTURE-PANICKED")
|
||||
}
|
||||
|
||||
func (s *RunS) TestPrintMissed(c *C) {
|
||||
result := &Result{Missed: 5}
|
||||
c.Check(result.String(), Equals, "OOPS: 0 passed, 5 MISSED")
|
||||
}
|
||||
|
||||
func (s *RunS) TestPrintAll(c *C) {
|
||||
result := &Result{Succeeded: 1, Skipped: 2, ExpectedFailures: 3,
|
||||
Panicked: 4, FixturePanicked: 5, Missed: 6}
|
||||
c.Check(result.String(), Equals,
|
||||
"OOPS: 1 passed, 2 skipped, 3 expected failures, 4 PANICKED, "+
|
||||
"5 FIXTURE-PANICKED, 6 MISSED")
|
||||
}
|
||||
|
||||
func (s *RunS) TestPrintRunError(c *C) {
|
||||
result := &Result{Succeeded: 1, Failed: 1,
|
||||
RunError: errors.New("Kaboom!")}
|
||||
c.Check(result.String(), Equals, "ERROR: Kaboom!")
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Verify that the method pattern flag works correctly.
|
||||
|
||||
func (s *RunS) TestFilterTestName(c *C) {
|
||||
helper := FixtureHelper{}
|
||||
output := String{}
|
||||
runConf := RunConf{Output: &output, Filter: "Test[91]"}
|
||||
Run(&helper, &runConf)
|
||||
c.Check(helper.calls[0], Equals, "SetUpSuite")
|
||||
c.Check(helper.calls[1], Equals, "SetUpTest")
|
||||
c.Check(helper.calls[2], Equals, "Test1")
|
||||
c.Check(helper.calls[3], Equals, "TearDownTest")
|
||||
c.Check(helper.calls[4], Equals, "TearDownSuite")
|
||||
c.Check(len(helper.calls), Equals, 5)
|
||||
}
|
||||
|
||||
func (s *RunS) TestFilterTestNameWithAll(c *C) {
|
||||
helper := FixtureHelper{}
|
||||
output := String{}
|
||||
runConf := RunConf{Output: &output, Filter: ".*"}
|
||||
Run(&helper, &runConf)
|
||||
c.Check(helper.calls[0], Equals, "SetUpSuite")
|
||||
c.Check(helper.calls[1], Equals, "SetUpTest")
|
||||
c.Check(helper.calls[2], Equals, "Test1")
|
||||
c.Check(helper.calls[3], Equals, "TearDownTest")
|
||||
c.Check(helper.calls[4], Equals, "SetUpTest")
|
||||
c.Check(helper.calls[5], Equals, "Test2")
|
||||
c.Check(helper.calls[6], Equals, "TearDownTest")
|
||||
c.Check(helper.calls[7], Equals, "TearDownSuite")
|
||||
c.Check(len(helper.calls), Equals, 8)
|
||||
}
|
||||
|
||||
func (s *RunS) TestFilterSuiteName(c *C) {
|
||||
helper := FixtureHelper{}
|
||||
output := String{}
|
||||
runConf := RunConf{Output: &output, Filter: "FixtureHelper"}
|
||||
Run(&helper, &runConf)
|
||||
c.Check(helper.calls[0], Equals, "SetUpSuite")
|
||||
c.Check(helper.calls[1], Equals, "SetUpTest")
|
||||
c.Check(helper.calls[2], Equals, "Test1")
|
||||
c.Check(helper.calls[3], Equals, "TearDownTest")
|
||||
c.Check(helper.calls[4], Equals, "SetUpTest")
|
||||
c.Check(helper.calls[5], Equals, "Test2")
|
||||
c.Check(helper.calls[6], Equals, "TearDownTest")
|
||||
c.Check(helper.calls[7], Equals, "TearDownSuite")
|
||||
c.Check(len(helper.calls), Equals, 8)
|
||||
}
|
||||
|
||||
func (s *RunS) TestFilterSuiteNameAndTestName(c *C) {
|
||||
helper := FixtureHelper{}
|
||||
output := String{}
|
||||
runConf := RunConf{Output: &output, Filter: "FixtureHelper\\.Test2"}
|
||||
Run(&helper, &runConf)
|
||||
c.Check(helper.calls[0], Equals, "SetUpSuite")
|
||||
c.Check(helper.calls[1], Equals, "SetUpTest")
|
||||
c.Check(helper.calls[2], Equals, "Test2")
|
||||
c.Check(helper.calls[3], Equals, "TearDownTest")
|
||||
c.Check(helper.calls[4], Equals, "TearDownSuite")
|
||||
c.Check(len(helper.calls), Equals, 5)
|
||||
}
|
||||
|
||||
func (s *RunS) TestFilterAllOut(c *C) {
|
||||
helper := FixtureHelper{}
|
||||
output := String{}
|
||||
runConf := RunConf{Output: &output, Filter: "NotFound"}
|
||||
Run(&helper, &runConf)
|
||||
c.Check(len(helper.calls), Equals, 0)
|
||||
}
|
||||
|
||||
func (s *RunS) TestRequirePartialMatch(c *C) {
|
||||
helper := FixtureHelper{}
|
||||
output := String{}
|
||||
runConf := RunConf{Output: &output, Filter: "est"}
|
||||
Run(&helper, &runConf)
|
||||
c.Check(len(helper.calls), Equals, 8)
|
||||
}
|
||||
|
||||
func (s *RunS) TestFilterError(c *C) {
|
||||
helper := FixtureHelper{}
|
||||
output := String{}
|
||||
runConf := RunConf{Output: &output, Filter: "]["}
|
||||
result := Run(&helper, &runConf)
|
||||
c.Check(result.String(), Equals,
|
||||
"ERROR: Bad filter expression: error parsing regexp: missing closing ]: `[`")
|
||||
c.Check(len(helper.calls), Equals, 0)
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Verify that List works correctly.
|
||||
|
||||
func (s *RunS) TestListFiltered(c *C) {
|
||||
names := List(&FixtureHelper{}, &RunConf{Filter: "1"})
|
||||
c.Assert(names, DeepEquals, []string{
|
||||
"FixtureHelper.Test1",
|
||||
})
|
||||
}
|
||||
|
||||
func (s *RunS) TestList(c *C) {
|
||||
names := List(&FixtureHelper{}, &RunConf{})
|
||||
c.Assert(names, DeepEquals, []string{
|
||||
"FixtureHelper.Test1",
|
||||
"FixtureHelper.Test2",
|
||||
})
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Verify that verbose mode prints tests which pass as well.
|
||||
|
||||
func (s *RunS) TestVerboseMode(c *C) {
|
||||
helper := FixtureHelper{}
|
||||
output := String{}
|
||||
runConf := RunConf{Output: &output, Verbose: true}
|
||||
Run(&helper, &runConf)
|
||||
|
||||
expected := "PASS: check_test\\.go:[0-9]+: FixtureHelper\\.Test1\t *[.0-9]+s\n" +
|
||||
"PASS: check_test\\.go:[0-9]+: FixtureHelper\\.Test2\t *[.0-9]+s\n"
|
||||
|
||||
c.Assert(output.value, Matches, expected)
|
||||
}
|
||||
|
||||
func (s *RunS) TestVerboseModeWithFailBeforePass(c *C) {
|
||||
helper := FixtureHelper{panicOn: "Test1"}
|
||||
output := String{}
|
||||
runConf := RunConf{Output: &output, Verbose: true}
|
||||
Run(&helper, &runConf)
|
||||
|
||||
expected := "(?s).*PANIC.*\n-+\n" + // Should have an extra line.
|
||||
"PASS: check_test\\.go:[0-9]+: FixtureHelper\\.Test2\t *[.0-9]+s\n"
|
||||
|
||||
c.Assert(output.value, Matches, expected)
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Verify the stream output mode. In this mode there's no output caching.
|
||||
|
||||
type StreamHelper struct {
|
||||
l2 sync.Mutex
|
||||
l3 sync.Mutex
|
||||
}
|
||||
|
||||
func (s *StreamHelper) SetUpSuite(c *C) {
|
||||
c.Log("0")
|
||||
}
|
||||
|
||||
func (s *StreamHelper) Test1(c *C) {
|
||||
c.Log("1")
|
||||
s.l2.Lock()
|
||||
s.l3.Lock()
|
||||
go func() {
|
||||
s.l2.Lock() // Wait for "2".
|
||||
c.Log("3")
|
||||
s.l3.Unlock()
|
||||
}()
|
||||
}
|
||||
|
||||
func (s *StreamHelper) Test2(c *C) {
|
||||
c.Log("2")
|
||||
s.l2.Unlock()
|
||||
s.l3.Lock() // Wait for "3".
|
||||
c.Fail()
|
||||
c.Log("4")
|
||||
}
|
||||
|
||||
func (s *RunS) TestStreamMode(c *C) {
|
||||
helper := &StreamHelper{}
|
||||
output := String{}
|
||||
runConf := RunConf{Output: &output, Stream: true}
|
||||
Run(helper, &runConf)
|
||||
|
||||
expected := "START: run_test\\.go:[0-9]+: StreamHelper\\.SetUpSuite\n0\n" +
|
||||
"PASS: run_test\\.go:[0-9]+: StreamHelper\\.SetUpSuite\t *[.0-9]+s\n\n" +
|
||||
"START: run_test\\.go:[0-9]+: StreamHelper\\.Test1\n1\n" +
|
||||
"PASS: run_test\\.go:[0-9]+: StreamHelper\\.Test1\t *[.0-9]+s\n\n" +
|
||||
"START: run_test\\.go:[0-9]+: StreamHelper\\.Test2\n2\n3\n4\n" +
|
||||
"FAIL: run_test\\.go:[0-9]+: StreamHelper\\.Test2\n\n"
|
||||
|
||||
c.Assert(output.value, Matches, expected)
|
||||
}
|
||||
|
||||
type StreamMissHelper struct{}
|
||||
|
||||
func (s *StreamMissHelper) SetUpSuite(c *C) {
|
||||
c.Log("0")
|
||||
c.Fail()
|
||||
}
|
||||
|
||||
func (s *StreamMissHelper) Test1(c *C) {
|
||||
c.Log("1")
|
||||
}
|
||||
|
||||
func (s *RunS) TestStreamModeWithMiss(c *C) {
|
||||
helper := &StreamMissHelper{}
|
||||
output := String{}
|
||||
runConf := RunConf{Output: &output, Stream: true}
|
||||
Run(helper, &runConf)
|
||||
|
||||
expected := "START: run_test\\.go:[0-9]+: StreamMissHelper\\.SetUpSuite\n0\n" +
|
||||
"FAIL: run_test\\.go:[0-9]+: StreamMissHelper\\.SetUpSuite\n\n" +
|
||||
"START: run_test\\.go:[0-9]+: StreamMissHelper\\.Test1\n" +
|
||||
"MISS: run_test\\.go:[0-9]+: StreamMissHelper\\.Test1\n\n"
|
||||
|
||||
c.Assert(output.value, Matches, expected)
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Verify that that the keep work dir request indeed does so.
|
||||
|
||||
type WorkDirSuite struct {}
|
||||
|
||||
func (s *WorkDirSuite) Test(c *C) {
|
||||
c.MkDir()
|
||||
}
|
||||
|
||||
func (s *RunS) TestKeepWorkDir(c *C) {
|
||||
output := String{}
|
||||
runConf := RunConf{Output: &output, Verbose: true, KeepWorkDir: true}
|
||||
result := Run(&WorkDirSuite{}, &runConf)
|
||||
|
||||
c.Assert(result.String(), Matches, ".*\nWORK=" + result.WorkDir)
|
||||
|
||||
stat, err := os.Stat(result.WorkDir)
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(stat.IsDir(), Equals, true)
|
||||
}
|
40
Makefile
40
Makefile
@ -6,10 +6,9 @@ checkdeps:
|
||||
|
||||
checkgopath:
|
||||
@echo "Checking if project is at ${GOPATH}"
|
||||
@for mcpath in $(echo ${GOPATH} | sed 's/:/\n/g' | grep -v Godeps); do if [ ! -d ${mcpath}/src/github.com/minio/minio ]; then echo "Project not found in ${mcpath}, please follow instructions provided at https://github.com/minio/minio/blob/master/CONTRIBUTING.md#setup-your-minio-github-repository" && exit 1; fi done
|
||||
@for mcpath in $(echo ${GOPATH} | sed 's/:/\n/g'); do if [ ! -d ${mcpath}/src/github.com/minio/minio ]; then echo "Project not found in ${mcpath}, please follow instructions provided at https://github.com/minio/minio/blob/master/CONTRIBUTING.md#setup-your-minio-github-repository" && exit 1; fi done
|
||||
|
||||
getdeps: checkdeps checkgopath
|
||||
@go get github.com/tools/godep && echo "Installed godep:"
|
||||
@go get github.com/golang/lint/golint && echo "Installed golint:"
|
||||
@go get golang.org/x/tools/cmd/vet && echo "Installed vet:"
|
||||
@go get github.com/fzipp/gocyclo && echo "Installed gocyclo:"
|
||||
@ -18,53 +17,42 @@ verifiers: getdeps vet fmt lint cyclo
|
||||
|
||||
vet:
|
||||
@echo "Running $@:"
|
||||
@go vet ./...
|
||||
@go vet .
|
||||
@go vet github.com/minio/minio/pkg...
|
||||
fmt:
|
||||
@echo "Running $@:"
|
||||
@test -z "$$(gofmt -s -l . | grep -v Godeps/_workspace/src/ | tee /dev/stderr)" || \
|
||||
echo "+ please format Go code with 'gofmt -s'"
|
||||
@gofmt -s -l *.go
|
||||
@gofmt -s -l pkg
|
||||
|
||||
lint:
|
||||
@echo "Running $@:"
|
||||
@test -z "$$(golint ./... | grep -v Godeps/_workspace/src/ | tee /dev/stderr)"
|
||||
@golint .
|
||||
@golint pkg
|
||||
|
||||
cyclo:
|
||||
@echo "Running $@:"
|
||||
@test -z "$$(gocyclo -over 25 . | grep -v Godeps/_workspace/src/ | tee /dev/stderr)"
|
||||
@gocyclo -over 25 .
|
||||
|
||||
build: getdeps verifiers
|
||||
@echo "Installing minio:"
|
||||
@godep go generate ./...
|
||||
@godep go test -race ./...
|
||||
@go generate ./...
|
||||
@go test -race github.com/minio/minio/pkg...
|
||||
|
||||
gomake-all: build
|
||||
@godep go install github.com/minio/minio
|
||||
@go install github.com/minio/minio
|
||||
|
||||
release: genversion
|
||||
@echo "Installing minio for new version.go:"
|
||||
@godep go install github.com/minio/minio
|
||||
@go install github.com/minio/minio
|
||||
|
||||
genversion:
|
||||
@echo "Generating new minio version.go"
|
||||
@godep go run genversion.go
|
||||
|
||||
godepupdate:
|
||||
@(env bash $(PWD)/buildscripts/updatedeps.sh)
|
||||
@go run genversion.go
|
||||
|
||||
install: gomake-all
|
||||
|
||||
save:
|
||||
@godep save ./...
|
||||
|
||||
restore:
|
||||
@godep restore
|
||||
|
||||
env:
|
||||
@godep go env
|
||||
|
||||
clean:
|
||||
@echo "Cleaning up all the generated files:"
|
||||
@rm -fv cover.out
|
||||
@rm -fv pkg/utils/split/TESTPREFIX.*
|
||||
@rm -fv minio
|
||||
@godep go clean
|
||||
@find Godeps -name "*.a" -type f -exec rm -vf {} \+
|
||||
|
@ -1,34 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# Minio Client (C) 2015 Minio, Inc.
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
_init() {
|
||||
godeps="Godeps/Godeps.json"
|
||||
filter="minio/minio"
|
||||
}
|
||||
|
||||
update() {
|
||||
for dep in $1; do
|
||||
godep update $dep;
|
||||
done
|
||||
}
|
||||
|
||||
main() {
|
||||
deps=$(env grep ImportPath ${godeps} | grep -v ${filter} | cut -f2 -d: | sed -e 's/,//' -e 's/^[ \t]*//' -e 's/[ \t]*$//' -e 's/\"//g' | tr '\n' ' ')
|
||||
update ${deps}
|
||||
}
|
||||
|
||||
_init && main "$@"
|
@ -20,7 +20,7 @@ import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/minio/cli"
|
||||
"github.com/minio/minio/internal/github.com/minio/cli"
|
||||
"github.com/minio/minio/pkg/controller"
|
||||
"github.com/minio/minio/pkg/donut"
|
||||
"github.com/minio/minio/pkg/server"
|
||||
|
@ -5,6 +5,9 @@ Just a few functions for helping humanize times and sizes.
|
||||
`go get` it as `github.com/dustin/go-humanize`, import it as
|
||||
`"github.com/dustin/go-humanize"`, use it as `humanize`
|
||||
|
||||
See [godoc](https://godoc.org/github.com/dustin/go-humanize) for
|
||||
complete documentation.
|
||||
|
||||
## Sizes
|
||||
|
||||
This lets you take numbers like `82854982` and convert them to useful
|
@ -115,7 +115,7 @@ func humanateBigBytes(s, base *big.Int, sizes []string) string {
|
||||
//
|
||||
// BigBytes(82854982) -> 83MB
|
||||
func BigBytes(s *big.Int) string {
|
||||
sizes := []string{"B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"}
|
||||
sizes := []string{"B", "kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"}
|
||||
return humanateBigBytes(s, bigSIExp, sizes)
|
||||
}
|
||||
|
@ -86,7 +86,7 @@ func humanateBytes(s uint64, base float64, sizes []string) string {
|
||||
//
|
||||
// Bytes(82854982) -> 83MB
|
||||
func Bytes(s uint64) string {
|
||||
sizes := []string{"B", "KB", "MB", "GB", "TB", "PB", "EB"}
|
||||
sizes := []string{"B", "kB", "MB", "GB", "TB", "PB", "EB"}
|
||||
return humanateBytes(s, 1000, sizes)
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ func Comma(v int64) string {
|
||||
v = 0 - v
|
||||
}
|
||||
|
||||
parts := []string{"", "", "", "", "", "", "", ""}
|
||||
parts := []string{"", "", "", "", "", "", ""}
|
||||
j := len(parts) - 1
|
||||
|
||||
for v > 999 {
|
192
internal/github.com/dustin/go-humanize/number.go
Normal file
192
internal/github.com/dustin/go-humanize/number.go
Normal file
@ -0,0 +1,192 @@
|
||||
package humanize
|
||||
|
||||
/*
|
||||
Slightly adapted from the source to fit go-humanize.
|
||||
|
||||
Author: https://github.com/gorhill
|
||||
Source: https://gist.github.com/gorhill/5285193
|
||||
|
||||
*/
|
||||
|
||||
import (
|
||||
"math"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
var (
|
||||
renderFloatPrecisionMultipliers = [...]float64{
|
||||
1,
|
||||
10,
|
||||
100,
|
||||
1000,
|
||||
10000,
|
||||
100000,
|
||||
1000000,
|
||||
10000000,
|
||||
100000000,
|
||||
1000000000,
|
||||
}
|
||||
|
||||
renderFloatPrecisionRounders = [...]float64{
|
||||
0.5,
|
||||
0.05,
|
||||
0.005,
|
||||
0.0005,
|
||||
0.00005,
|
||||
0.000005,
|
||||
0.0000005,
|
||||
0.00000005,
|
||||
0.000000005,
|
||||
0.0000000005,
|
||||
}
|
||||
)
|
||||
|
||||
// FormatFloat produces a formatted number as string based on the following user-specified criteria:
|
||||
// * thousands separator
|
||||
// * decimal separator
|
||||
// * decimal precision
|
||||
//
|
||||
// Usage: s := RenderFloat(format, n)
|
||||
// The format parameter tells how to render the number n.
|
||||
//
|
||||
// See examples: http://play.golang.org/p/LXc1Ddm1lJ
|
||||
//
|
||||
// Examples of format strings, given n = 12345.6789:
|
||||
// "#,###.##" => "12,345.67"
|
||||
// "#,###." => "12,345"
|
||||
// "#,###" => "12345,678"
|
||||
// "#\u202F###,##" => "12 345,68"
|
||||
// "#.###,###### => 12.345,678900
|
||||
// "" (aka default format) => 12,345.67
|
||||
//
|
||||
// The highest precision allowed is 9 digits after the decimal symbol.
|
||||
// There is also a version for integer number, FormatInteger(),
|
||||
// which is convenient for calls within template.
|
||||
func FormatFloat(format string, n float64) string {
|
||||
// Special cases:
|
||||
// NaN = "NaN"
|
||||
// +Inf = "+Infinity"
|
||||
// -Inf = "-Infinity"
|
||||
if math.IsNaN(n) {
|
||||
return "NaN"
|
||||
}
|
||||
if n > math.MaxFloat64 {
|
||||
return "Infinity"
|
||||
}
|
||||
if n < -math.MaxFloat64 {
|
||||
return "-Infinity"
|
||||
}
|
||||
|
||||
// default format
|
||||
precision := 2
|
||||
decimalStr := "."
|
||||
thousandStr := ","
|
||||
positiveStr := ""
|
||||
negativeStr := "-"
|
||||
|
||||
if len(format) > 0 {
|
||||
format := []rune(format)
|
||||
|
||||
// If there is an explicit format directive,
|
||||
// then default values are these:
|
||||
precision = 9
|
||||
thousandStr = ""
|
||||
|
||||
// collect indices of meaningful formatting directives
|
||||
formatIndx := []int{}
|
||||
for i, char := range format {
|
||||
if char != '#' && char != '0' {
|
||||
formatIndx = append(formatIndx, i)
|
||||
}
|
||||
}
|
||||
|
||||
if len(formatIndx) > 0 {
|
||||
// Directive at index 0:
|
||||
// Must be a '+'
|
||||
// Raise an error if not the case
|
||||
// index: 0123456789
|
||||
// +0.000,000
|
||||
// +000,000.0
|
||||
// +0000.00
|
||||
// +0000
|
||||
if formatIndx[0] == 0 {
|
||||
if format[formatIndx[0]] != '+' {
|
||||
panic("RenderFloat(): invalid positive sign directive")
|
||||
}
|
||||
positiveStr = "+"
|
||||
formatIndx = formatIndx[1:]
|
||||
}
|
||||
|
||||
// Two directives:
|
||||
// First is thousands separator
|
||||
// Raise an error if not followed by 3-digit
|
||||
// 0123456789
|
||||
// 0.000,000
|
||||
// 000,000.00
|
||||
if len(formatIndx) == 2 {
|
||||
if (formatIndx[1] - formatIndx[0]) != 4 {
|
||||
panic("RenderFloat(): thousands separator directive must be followed by 3 digit-specifiers")
|
||||
}
|
||||
thousandStr = string(format[formatIndx[0]])
|
||||
formatIndx = formatIndx[1:]
|
||||
}
|
||||
|
||||
// One directive:
|
||||
// Directive is decimal separator
|
||||
// The number of digit-specifier following the separator indicates wanted precision
|
||||
// 0123456789
|
||||
// 0.00
|
||||
// 000,0000
|
||||
if len(formatIndx) == 1 {
|
||||
decimalStr = string(format[formatIndx[0]])
|
||||
precision = len(format) - formatIndx[0] - 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// generate sign part
|
||||
var signStr string
|
||||
if n >= 0.000000001 {
|
||||
signStr = positiveStr
|
||||
} else if n <= -0.000000001 {
|
||||
signStr = negativeStr
|
||||
n = -n
|
||||
} else {
|
||||
signStr = ""
|
||||
n = 0.0
|
||||
}
|
||||
|
||||
// split number into integer and fractional parts
|
||||
intf, fracf := math.Modf(n + renderFloatPrecisionRounders[precision])
|
||||
|
||||
// generate integer part string
|
||||
intStr := strconv.Itoa(int(intf))
|
||||
|
||||
// add thousand separator if required
|
||||
if len(thousandStr) > 0 {
|
||||
for i := len(intStr); i > 3; {
|
||||
i -= 3
|
||||
intStr = intStr[:i] + thousandStr + intStr[i:]
|
||||
}
|
||||
}
|
||||
|
||||
// no fractional part, we can leave now
|
||||
if precision == 0 {
|
||||
return signStr + intStr
|
||||
}
|
||||
|
||||
// generate fractional part
|
||||
fracStr := strconv.Itoa(int(fracf * renderFloatPrecisionMultipliers[precision]))
|
||||
// may need padding
|
||||
if len(fracStr) < precision {
|
||||
fracStr = "000000000000000"[:precision-len(fracStr)] + fracStr
|
||||
}
|
||||
|
||||
return signStr + intStr + decimalStr + fracStr
|
||||
}
|
||||
|
||||
// FormatInteger produces a formatted number as string.
|
||||
// See FormatFloat.
|
||||
func FormatInteger(format string, n int) string {
|
||||
return FormatFloat(format, float64(n))
|
||||
}
|
@ -14,8 +14,8 @@ import (
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/facebookgo/clock"
|
||||
"github.com/facebookgo/stats"
|
||||
"github.com/minio/minio/internal/github.com/facebookgo/clock"
|
||||
"github.com/minio/minio/internal/github.com/facebookgo/stats"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -100,7 +100,7 @@ func (h HTTP) Serve(s *http.Server, l net.Listener) Server {
|
||||
}
|
||||
|
||||
// ListenAndServe returns a Server for the given http.Server. It is equivalent
|
||||
// to ListendAndServe from the standard library, but returns immediately.
|
||||
// to ListenAndServe from the standard library, but returns immediately.
|
||||
// Requests will be accepted in a background goroutine. If the http.Server has
|
||||
// a non-nil TLSConfig, a TLS enabled listener will be setup.
|
||||
func (h HTTP) ListenAndServe(s *http.Server) (Server, error) {
|
@ -43,6 +43,10 @@ m := structs.Map(server)
|
||||
// => ["gopher", 123456, true]
|
||||
v := structs.Values(server)
|
||||
|
||||
// Convert the names of a struct to a []string
|
||||
// (see "Names methods" for more info about fields)
|
||||
n := structs.Names(server)
|
||||
|
||||
// Convert the values of a struct to a []*Field
|
||||
// (see "Field methods" for more info about fields)
|
||||
f := structs.Fields(server)
|
||||
@ -73,8 +77,9 @@ s := structs.New(server)
|
||||
m := s.Map() // Get a map[string]interface{}
|
||||
v := s.Values() // Get a []interface{}
|
||||
f := s.Fields() // Get a []*Field
|
||||
n := s.Names() // Get a []string
|
||||
f := s.Field(name) // Get a *Field based on the given field name
|
||||
f, ok := s.FieldsOk(name) // Get a *Field based on the given field name
|
||||
f, ok := s.FieldOk(name) // Get a *Field based on the given field name
|
||||
n := s.Name() // Get the struct name
|
||||
h := s.HasZero() // Check if any field is initialized
|
||||
z := s.IsZero() // Check if all fields are initialized
|
@ -92,7 +92,9 @@ func (s *Struct) Map() map[string]interface{} {
|
||||
if IsStruct(val.Interface()) && !tagOpts.Has("omitnested") {
|
||||
// look out for embedded structs, and convert them to a
|
||||
// map[string]interface{} too
|
||||
finalVal = Map(val.Interface())
|
||||
n := New(val.Interface())
|
||||
n.TagName = s.TagName
|
||||
finalVal = n.Map()
|
||||
} else {
|
||||
finalVal = val.Interface()
|
||||
}
|
||||
@ -171,6 +173,25 @@ func (s *Struct) Fields() []*Field {
|
||||
return getFields(s.value, s.TagName)
|
||||
}
|
||||
|
||||
// Names returns a slice of field names. A struct tag with the content of "-"
|
||||
// ignores the checking of that particular field. Example:
|
||||
//
|
||||
// // Field is ignored by this package.
|
||||
// Field bool `structs:"-"`
|
||||
//
|
||||
// It panics if s's kind is not struct.
|
||||
func (s *Struct) Names() []string {
|
||||
fields := getFields(s.value, s.TagName)
|
||||
|
||||
names := make([]string, len(fields))
|
||||
|
||||
for i, field := range fields {
|
||||
names[i] = field.Name()
|
||||
}
|
||||
|
||||
return names
|
||||
}
|
||||
|
||||
func getFields(v reflect.Value, tagName string) []*Field {
|
||||
if v.Kind() == reflect.Ptr {
|
||||
v = v.Elem()
|
||||
@ -387,6 +408,12 @@ func Fields(s interface{}) []*Field {
|
||||
return New(s).Fields()
|
||||
}
|
||||
|
||||
// Names returns a slice of field names. For more info refer to Struct types
|
||||
// Names() method. It panics if s's kind is not struct.
|
||||
func Names(s interface{}) []string {
|
||||
return New(s).Names()
|
||||
}
|
||||
|
||||
// IsZero returns true if all fields is equal to a zero value. For more info
|
||||
// refer to Struct types IsZero() method. It panics if s's kind is not struct.
|
||||
func IsZero(s interface{}) bool {
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user