*: move ./Godeps/_workspace/src/ to ./vendor/
This commit is contained in:
parent
38be227aa2
commit
08b12a0e5c
621 changed files with 512 additions and 59584 deletions
2
Godeps/_workspace/.gitignore
generated
vendored
2
Godeps/_workspace/.gitignore
generated
vendored
|
@ -1,2 +0,0 @@
|
||||||
/pkg
|
|
||||||
/bin
|
|
180
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/array_test.go
generated
vendored
180
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/array_test.go
generated
vendored
|
@ -1,180 +0,0 @@
|
||||||
package goquery
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestFirst(t *testing.T) {
|
|
||||||
sel := Doc().Find(".pvk-content").First()
|
|
||||||
assertLength(t, sel.Nodes, 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFirstEmpty(t *testing.T) {
|
|
||||||
sel := Doc().Find(".pvk-zzcontentzz").First()
|
|
||||||
assertLength(t, sel.Nodes, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFirstRollback(t *testing.T) {
|
|
||||||
sel := Doc().Find(".pvk-content")
|
|
||||||
sel2 := sel.First().End()
|
|
||||||
assertEqual(t, sel, sel2)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestLast(t *testing.T) {
|
|
||||||
sel := Doc().Find(".pvk-content").Last()
|
|
||||||
assertLength(t, sel.Nodes, 1)
|
|
||||||
|
|
||||||
// Should contain Footer
|
|
||||||
foot := Doc().Find(".footer")
|
|
||||||
if !sel.Contains(foot.Nodes[0]) {
|
|
||||||
t.Error("Last .pvk-content should contain .footer.")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestLastEmpty(t *testing.T) {
|
|
||||||
sel := Doc().Find(".pvk-zzcontentzz").Last()
|
|
||||||
assertLength(t, sel.Nodes, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestLastRollback(t *testing.T) {
|
|
||||||
sel := Doc().Find(".pvk-content")
|
|
||||||
sel2 := sel.Last().End()
|
|
||||||
assertEqual(t, sel, sel2)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestEq(t *testing.T) {
|
|
||||||
sel := Doc().Find(".pvk-content").Eq(1)
|
|
||||||
assertLength(t, sel.Nodes, 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestEqNegative(t *testing.T) {
|
|
||||||
sel := Doc().Find(".pvk-content").Eq(-1)
|
|
||||||
assertLength(t, sel.Nodes, 1)
|
|
||||||
|
|
||||||
// Should contain Footer
|
|
||||||
foot := Doc().Find(".footer")
|
|
||||||
if !sel.Contains(foot.Nodes[0]) {
|
|
||||||
t.Error("Index -1 of .pvk-content should contain .footer.")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestEqEmpty(t *testing.T) {
|
|
||||||
sel := Doc().Find("something_random_that_does_not_exists").Eq(0)
|
|
||||||
assertLength(t, sel.Nodes, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestEqInvalidPositive(t *testing.T) {
|
|
||||||
sel := Doc().Find(".pvk-content").Eq(3)
|
|
||||||
assertLength(t, sel.Nodes, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestEqInvalidNegative(t *testing.T) {
|
|
||||||
sel := Doc().Find(".pvk-content").Eq(-4)
|
|
||||||
assertLength(t, sel.Nodes, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestEqRollback(t *testing.T) {
|
|
||||||
sel := Doc().Find(".pvk-content")
|
|
||||||
sel2 := sel.Eq(1).End()
|
|
||||||
assertEqual(t, sel, sel2)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSlice(t *testing.T) {
|
|
||||||
sel := Doc().Find(".pvk-content").Slice(0, 2)
|
|
||||||
|
|
||||||
assertLength(t, sel.Nodes, 2)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSliceOutOfBounds(t *testing.T) {
|
|
||||||
defer assertPanic(t)
|
|
||||||
Doc().Find(".pvk-content").Slice(2, 12)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestNegativeSliceStart(t *testing.T) {
|
|
||||||
sel := Doc().Find(".container-fluid").Slice(-2, 3)
|
|
||||||
assertLength(t, sel.Nodes, 1)
|
|
||||||
assertSelectionIs(t, sel.Eq(0), "#cf3")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestNegativeSliceEnd(t *testing.T) {
|
|
||||||
sel := Doc().Find(".container-fluid").Slice(1, -1)
|
|
||||||
assertLength(t, sel.Nodes, 2)
|
|
||||||
assertSelectionIs(t, sel.Eq(0), "#cf2")
|
|
||||||
assertSelectionIs(t, sel.Eq(1), "#cf3")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestNegativeSliceBoth(t *testing.T) {
|
|
||||||
sel := Doc().Find(".container-fluid").Slice(-3, -1)
|
|
||||||
assertLength(t, sel.Nodes, 2)
|
|
||||||
assertSelectionIs(t, sel.Eq(0), "#cf2")
|
|
||||||
assertSelectionIs(t, sel.Eq(1), "#cf3")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestNegativeSliceOutOfBounds(t *testing.T) {
|
|
||||||
defer assertPanic(t)
|
|
||||||
Doc().Find(".container-fluid").Slice(-12, -7)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSliceRollback(t *testing.T) {
|
|
||||||
sel := Doc().Find(".pvk-content")
|
|
||||||
sel2 := sel.Slice(0, 2).End()
|
|
||||||
assertEqual(t, sel, sel2)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestGet(t *testing.T) {
|
|
||||||
sel := Doc().Find(".pvk-content")
|
|
||||||
node := sel.Get(1)
|
|
||||||
if sel.Nodes[1] != node {
|
|
||||||
t.Errorf("Expected node %v to be %v.", node, sel.Nodes[1])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestGetNegative(t *testing.T) {
|
|
||||||
sel := Doc().Find(".pvk-content")
|
|
||||||
node := sel.Get(-3)
|
|
||||||
if sel.Nodes[0] != node {
|
|
||||||
t.Errorf("Expected node %v to be %v.", node, sel.Nodes[0])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestGetInvalid(t *testing.T) {
|
|
||||||
defer assertPanic(t)
|
|
||||||
sel := Doc().Find(".pvk-content")
|
|
||||||
sel.Get(129)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestIndex(t *testing.T) {
|
|
||||||
sel := Doc().Find(".pvk-content")
|
|
||||||
if i := sel.Index(); i != 1 {
|
|
||||||
t.Errorf("Expected index of 1, got %v.", i)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestIndexSelector(t *testing.T) {
|
|
||||||
sel := Doc().Find(".hero-unit")
|
|
||||||
if i := sel.IndexSelector("div"); i != 4 {
|
|
||||||
t.Errorf("Expected index of 4, got %v.", i)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestIndexOfNode(t *testing.T) {
|
|
||||||
sel := Doc().Find("div.pvk-gutter")
|
|
||||||
if i := sel.IndexOfNode(sel.Nodes[1]); i != 1 {
|
|
||||||
t.Errorf("Expected index of 1, got %v.", i)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestIndexOfNilNode(t *testing.T) {
|
|
||||||
sel := Doc().Find("div.pvk-gutter")
|
|
||||||
if i := sel.IndexOfNode(nil); i != -1 {
|
|
||||||
t.Errorf("Expected index of -1, got %v.", i)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestIndexOfSelection(t *testing.T) {
|
|
||||||
sel := Doc().Find("div")
|
|
||||||
sel2 := Doc().Find(".hero-unit")
|
|
||||||
if i := sel.IndexOfSelection(sel2); i != 4 {
|
|
||||||
t.Errorf("Expected index of 4, got %v.", i)
|
|
||||||
}
|
|
||||||
}
|
|
112
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/bench_array_test.go
generated
vendored
112
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/bench_array_test.go
generated
vendored
|
@ -1,112 +0,0 @@
|
||||||
package goquery
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func BenchmarkFirst(b *testing.B) {
|
|
||||||
b.StopTimer()
|
|
||||||
sel := DocB().Find("dd")
|
|
||||||
b.StartTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
sel.First()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkLast(b *testing.B) {
|
|
||||||
b.StopTimer()
|
|
||||||
sel := DocB().Find("dd")
|
|
||||||
b.StartTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
sel.Last()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkEq(b *testing.B) {
|
|
||||||
b.StopTimer()
|
|
||||||
sel := DocB().Find("dd")
|
|
||||||
j := 0
|
|
||||||
b.StartTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
sel.Eq(j)
|
|
||||||
if j++; j >= sel.Length() {
|
|
||||||
j = 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkSlice(b *testing.B) {
|
|
||||||
b.StopTimer()
|
|
||||||
sel := DocB().Find("dd")
|
|
||||||
j := 0
|
|
||||||
b.StartTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
sel.Slice(j, j+4)
|
|
||||||
if j++; j >= (sel.Length() - 4) {
|
|
||||||
j = 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkGet(b *testing.B) {
|
|
||||||
b.StopTimer()
|
|
||||||
sel := DocB().Find("dd")
|
|
||||||
j := 0
|
|
||||||
b.StartTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
sel.Get(j)
|
|
||||||
if j++; j >= sel.Length() {
|
|
||||||
j = 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkIndex(b *testing.B) {
|
|
||||||
var j int
|
|
||||||
|
|
||||||
b.StopTimer()
|
|
||||||
sel := DocB().Find("#Main")
|
|
||||||
b.StartTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
j = sel.Index()
|
|
||||||
}
|
|
||||||
b.Logf("Index=%d", j)
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkIndexSelector(b *testing.B) {
|
|
||||||
var j int
|
|
||||||
|
|
||||||
b.StopTimer()
|
|
||||||
sel := DocB().Find("#manual-nav dl dd:nth-child(1)")
|
|
||||||
b.StartTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
j = sel.IndexSelector("dd")
|
|
||||||
}
|
|
||||||
b.Logf("IndexSelector=%d", j)
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkIndexOfNode(b *testing.B) {
|
|
||||||
var j int
|
|
||||||
|
|
||||||
b.StopTimer()
|
|
||||||
sel := DocB().Find("span a")
|
|
||||||
sel2 := DocB().Find("span a:nth-child(3)")
|
|
||||||
n := sel2.Get(0)
|
|
||||||
b.StartTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
j = sel.IndexOfNode(n)
|
|
||||||
}
|
|
||||||
b.Logf("IndexOfNode=%d", j)
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkIndexOfSelection(b *testing.B) {
|
|
||||||
var j int
|
|
||||||
b.StopTimer()
|
|
||||||
sel := DocB().Find("span a")
|
|
||||||
sel2 := DocB().Find("span a:nth-child(3)")
|
|
||||||
b.StartTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
j = sel.IndexOfSelection(sel2)
|
|
||||||
}
|
|
||||||
b.Logf("IndexOfSelection=%d", j)
|
|
||||||
}
|
|
42
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/bench_example_test.go
generated
vendored
42
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/bench_example_test.go
generated
vendored
|
@ -1,42 +0,0 @@
|
||||||
package goquery
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"fmt"
|
|
||||||
"strconv"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func BenchmarkMetalReviewExample(b *testing.B) {
|
|
||||||
var n int
|
|
||||||
var buf bytes.Buffer
|
|
||||||
|
|
||||||
b.StopTimer()
|
|
||||||
doc := loadDoc("metalreview.html")
|
|
||||||
b.StartTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
doc.Find(".slider-row:nth-child(1) .slider-item").Each(func(i int, s *Selection) {
|
|
||||||
var band, title string
|
|
||||||
var score float64
|
|
||||||
var e error
|
|
||||||
|
|
||||||
n++
|
|
||||||
// For each item found, get the band, title and score, and print it
|
|
||||||
band = s.Find("strong").Text()
|
|
||||||
title = s.Find("em").Text()
|
|
||||||
if score, e = strconv.ParseFloat(s.Find(".score").Text(), 64); e != nil {
|
|
||||||
// Not a valid float, ignore score
|
|
||||||
if n <= 4 {
|
|
||||||
buf.WriteString(fmt.Sprintf("Review %d: %s - %s.\n", i, band, title))
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Print all, including score
|
|
||||||
if n <= 4 {
|
|
||||||
buf.WriteString(fmt.Sprintf("Review %d: %s - %s (%2.1f).\n", i, band, title, score))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
b.Log(buf.String())
|
|
||||||
b.Logf("MetalReviewExample=%d", n)
|
|
||||||
}
|
|
72
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/bench_expand_test.go
generated
vendored
72
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/bench_expand_test.go
generated
vendored
|
@ -1,72 +0,0 @@
|
||||||
package goquery
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func BenchmarkAdd(b *testing.B) {
|
|
||||||
var n int
|
|
||||||
|
|
||||||
b.StopTimer()
|
|
||||||
sel := DocB().Find("dd")
|
|
||||||
b.StartTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
if n == 0 {
|
|
||||||
n = sel.Add("h2[title]").Length()
|
|
||||||
} else {
|
|
||||||
sel.Add("h2[title]")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
b.Logf("Add=%d", n)
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkAddSelection(b *testing.B) {
|
|
||||||
var n int
|
|
||||||
|
|
||||||
b.StopTimer()
|
|
||||||
sel := DocB().Find("dd")
|
|
||||||
sel2 := DocB().Find("h2[title]")
|
|
||||||
b.StartTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
if n == 0 {
|
|
||||||
n = sel.AddSelection(sel2).Length()
|
|
||||||
} else {
|
|
||||||
sel.AddSelection(sel2)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
b.Logf("AddSelection=%d", n)
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkAddNodes(b *testing.B) {
|
|
||||||
var n int
|
|
||||||
|
|
||||||
b.StopTimer()
|
|
||||||
sel := DocB().Find("dd")
|
|
||||||
sel2 := DocB().Find("h2[title]")
|
|
||||||
nodes := sel2.Nodes
|
|
||||||
b.StartTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
if n == 0 {
|
|
||||||
n = sel.AddNodes(nodes...).Length()
|
|
||||||
} else {
|
|
||||||
sel.AddNodes(nodes...)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
b.Logf("AddNodes=%d", n)
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkAndSelf(b *testing.B) {
|
|
||||||
var n int
|
|
||||||
|
|
||||||
b.StopTimer()
|
|
||||||
sel := DocB().Find("dd").Parent()
|
|
||||||
b.StartTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
if n == 0 {
|
|
||||||
n = sel.AndSelf().Length()
|
|
||||||
} else {
|
|
||||||
sel.AndSelf()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
b.Logf("AndSelf=%d", n)
|
|
||||||
}
|
|
212
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/bench_filter_test.go
generated
vendored
212
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/bench_filter_test.go
generated
vendored
|
@ -1,212 +0,0 @@
|
||||||
package goquery
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func BenchmarkFilter(b *testing.B) {
|
|
||||||
var n int
|
|
||||||
|
|
||||||
b.StopTimer()
|
|
||||||
sel := DocW().Find("li")
|
|
||||||
b.StartTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
if n == 0 {
|
|
||||||
n = sel.Filter(".toclevel-1").Length()
|
|
||||||
} else {
|
|
||||||
sel.Filter(".toclevel-1")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
b.Logf("Filter=%d", n)
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkNot(b *testing.B) {
|
|
||||||
var n int
|
|
||||||
|
|
||||||
b.StopTimer()
|
|
||||||
sel := DocW().Find("li")
|
|
||||||
b.StartTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
if n == 0 {
|
|
||||||
n = sel.Not(".toclevel-2").Length()
|
|
||||||
} else {
|
|
||||||
sel.Filter(".toclevel-2")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
b.Logf("Not=%d", n)
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkFilterFunction(b *testing.B) {
|
|
||||||
var n int
|
|
||||||
|
|
||||||
b.StopTimer()
|
|
||||||
sel := DocW().Find("li")
|
|
||||||
f := func(i int, s *Selection) bool {
|
|
||||||
return len(s.Get(0).Attr) > 0
|
|
||||||
}
|
|
||||||
b.StartTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
if n == 0 {
|
|
||||||
n = sel.FilterFunction(f).Length()
|
|
||||||
} else {
|
|
||||||
sel.FilterFunction(f)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
b.Logf("FilterFunction=%d", n)
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkNotFunction(b *testing.B) {
|
|
||||||
var n int
|
|
||||||
|
|
||||||
b.StopTimer()
|
|
||||||
sel := DocW().Find("li")
|
|
||||||
f := func(i int, s *Selection) bool {
|
|
||||||
return len(s.Get(0).Attr) > 0
|
|
||||||
}
|
|
||||||
b.StartTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
if n == 0 {
|
|
||||||
n = sel.NotFunction(f).Length()
|
|
||||||
} else {
|
|
||||||
sel.NotFunction(f)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
b.Logf("NotFunction=%d", n)
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkFilterNodes(b *testing.B) {
|
|
||||||
var n int
|
|
||||||
|
|
||||||
b.StopTimer()
|
|
||||||
sel := DocW().Find("li")
|
|
||||||
sel2 := DocW().Find(".toclevel-2")
|
|
||||||
nodes := sel2.Nodes
|
|
||||||
b.StartTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
if n == 0 {
|
|
||||||
n = sel.FilterNodes(nodes...).Length()
|
|
||||||
} else {
|
|
||||||
sel.FilterNodes(nodes...)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
b.Logf("FilterNodes=%d", n)
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkNotNodes(b *testing.B) {
|
|
||||||
var n int
|
|
||||||
|
|
||||||
b.StopTimer()
|
|
||||||
sel := DocW().Find("li")
|
|
||||||
sel2 := DocW().Find(".toclevel-1")
|
|
||||||
nodes := sel2.Nodes
|
|
||||||
b.StartTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
if n == 0 {
|
|
||||||
n = sel.NotNodes(nodes...).Length()
|
|
||||||
} else {
|
|
||||||
sel.NotNodes(nodes...)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
b.Logf("NotNodes=%d", n)
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkFilterSelection(b *testing.B) {
|
|
||||||
var n int
|
|
||||||
|
|
||||||
b.StopTimer()
|
|
||||||
sel := DocW().Find("li")
|
|
||||||
sel2 := DocW().Find(".toclevel-2")
|
|
||||||
b.StartTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
if n == 0 {
|
|
||||||
n = sel.FilterSelection(sel2).Length()
|
|
||||||
} else {
|
|
||||||
sel.FilterSelection(sel2)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
b.Logf("FilterSelection=%d", n)
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkNotSelection(b *testing.B) {
|
|
||||||
var n int
|
|
||||||
|
|
||||||
b.StopTimer()
|
|
||||||
sel := DocW().Find("li")
|
|
||||||
sel2 := DocW().Find(".toclevel-1")
|
|
||||||
b.StartTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
if n == 0 {
|
|
||||||
n = sel.NotSelection(sel2).Length()
|
|
||||||
} else {
|
|
||||||
sel.NotSelection(sel2)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
b.Logf("NotSelection=%d", n)
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkHas(b *testing.B) {
|
|
||||||
var n int
|
|
||||||
|
|
||||||
b.StopTimer()
|
|
||||||
sel := DocW().Find("h2")
|
|
||||||
b.StartTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
if n == 0 {
|
|
||||||
n = sel.Has(".editsection").Length()
|
|
||||||
} else {
|
|
||||||
sel.Has(".editsection")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
b.Logf("Has=%d", n)
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkHasNodes(b *testing.B) {
|
|
||||||
var n int
|
|
||||||
|
|
||||||
b.StopTimer()
|
|
||||||
sel := DocW().Find("li")
|
|
||||||
sel2 := DocW().Find(".tocnumber")
|
|
||||||
nodes := sel2.Nodes
|
|
||||||
b.StartTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
if n == 0 {
|
|
||||||
n = sel.HasNodes(nodes...).Length()
|
|
||||||
} else {
|
|
||||||
sel.HasNodes(nodes...)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
b.Logf("HasNodes=%d", n)
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkHasSelection(b *testing.B) {
|
|
||||||
var n int
|
|
||||||
|
|
||||||
b.StopTimer()
|
|
||||||
sel := DocW().Find("li")
|
|
||||||
sel2 := DocW().Find(".tocnumber")
|
|
||||||
b.StartTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
if n == 0 {
|
|
||||||
n = sel.HasSelection(sel2).Length()
|
|
||||||
} else {
|
|
||||||
sel.HasSelection(sel2)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
b.Logf("HasSelection=%d", n)
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkEnd(b *testing.B) {
|
|
||||||
var n int
|
|
||||||
|
|
||||||
b.StopTimer()
|
|
||||||
sel := DocW().Find("li").Has(".tocnumber")
|
|
||||||
b.StartTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
if n == 0 {
|
|
||||||
n = sel.End().Length()
|
|
||||||
} else {
|
|
||||||
sel.End()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
b.Logf("End=%d", n)
|
|
||||||
}
|
|
62
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/bench_iteration_test.go
generated
vendored
62
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/bench_iteration_test.go
generated
vendored
|
@ -1,62 +0,0 @@
|
||||||
package goquery
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func BenchmarkEach(b *testing.B) {
|
|
||||||
var tmp, n int
|
|
||||||
|
|
||||||
b.StopTimer()
|
|
||||||
sel := DocW().Find("td")
|
|
||||||
f := func(i int, s *Selection) {
|
|
||||||
tmp++
|
|
||||||
}
|
|
||||||
b.StartTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
sel.Each(f)
|
|
||||||
if n == 0 {
|
|
||||||
n = tmp
|
|
||||||
}
|
|
||||||
}
|
|
||||||
b.Logf("Each=%d", n)
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkMap(b *testing.B) {
|
|
||||||
var tmp, n int
|
|
||||||
|
|
||||||
b.StopTimer()
|
|
||||||
sel := DocW().Find("td")
|
|
||||||
f := func(i int, s *Selection) string {
|
|
||||||
tmp++
|
|
||||||
return string(tmp)
|
|
||||||
}
|
|
||||||
b.StartTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
sel.Map(f)
|
|
||||||
if n == 0 {
|
|
||||||
n = tmp
|
|
||||||
}
|
|
||||||
}
|
|
||||||
b.Logf("Map=%d", n)
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkEachWithBreak(b *testing.B) {
|
|
||||||
var tmp, n int
|
|
||||||
|
|
||||||
b.StopTimer()
|
|
||||||
sel := DocW().Find("td")
|
|
||||||
f := func(i int, s *Selection) bool {
|
|
||||||
tmp++
|
|
||||||
return tmp < 10
|
|
||||||
}
|
|
||||||
b.StartTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
tmp = 0
|
|
||||||
sel.EachWithBreak(f)
|
|
||||||
if n == 0 {
|
|
||||||
n = tmp
|
|
||||||
}
|
|
||||||
}
|
|
||||||
b.Logf("Each=%d", n)
|
|
||||||
}
|
|
47
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/bench_property_test.go
generated
vendored
47
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/bench_property_test.go
generated
vendored
|
@ -1,47 +0,0 @@
|
||||||
package goquery
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func BenchmarkAttr(b *testing.B) {
|
|
||||||
var s string
|
|
||||||
|
|
||||||
b.StopTimer()
|
|
||||||
sel := DocW().Find("h1")
|
|
||||||
b.StartTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
s, _ = sel.Attr("id")
|
|
||||||
}
|
|
||||||
b.Logf("Attr=%s", s)
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkText(b *testing.B) {
|
|
||||||
b.StopTimer()
|
|
||||||
sel := DocW().Find("h2")
|
|
||||||
b.StartTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
sel.Text()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkLength(b *testing.B) {
|
|
||||||
var n int
|
|
||||||
|
|
||||||
b.StopTimer()
|
|
||||||
sel := DocW().Find("h2")
|
|
||||||
b.StartTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
n = sel.Length()
|
|
||||||
}
|
|
||||||
b.Logf("Length=%d", n)
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkHtml(b *testing.B) {
|
|
||||||
b.StopTimer()
|
|
||||||
sel := DocW().Find("h2")
|
|
||||||
b.StartTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
sel.Html()
|
|
||||||
}
|
|
||||||
}
|
|
97
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/bench_query_test.go
generated
vendored
97
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/bench_query_test.go
generated
vendored
|
@ -1,97 +0,0 @@
|
||||||
package goquery
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func BenchmarkIs(b *testing.B) {
|
|
||||||
var y bool
|
|
||||||
|
|
||||||
b.StopTimer()
|
|
||||||
sel := DocW().Find("li")
|
|
||||||
b.StartTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
y = sel.Is(".toclevel-2")
|
|
||||||
}
|
|
||||||
b.Logf("Is=%v", y)
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkIsPositional(b *testing.B) {
|
|
||||||
var y bool
|
|
||||||
|
|
||||||
b.StopTimer()
|
|
||||||
sel := DocW().Find("li")
|
|
||||||
b.StartTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
y = sel.Is("li:nth-child(2)")
|
|
||||||
}
|
|
||||||
b.Logf("IsPositional=%v", y)
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkIsFunction(b *testing.B) {
|
|
||||||
var y bool
|
|
||||||
|
|
||||||
b.StopTimer()
|
|
||||||
sel := DocW().Find(".toclevel-1")
|
|
||||||
f := func(i int, s *Selection) bool {
|
|
||||||
return i == 8
|
|
||||||
}
|
|
||||||
b.StartTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
y = sel.IsFunction(f)
|
|
||||||
}
|
|
||||||
b.Logf("IsFunction=%v", y)
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkIsSelection(b *testing.B) {
|
|
||||||
var y bool
|
|
||||||
|
|
||||||
b.StopTimer()
|
|
||||||
sel := DocW().Find("li")
|
|
||||||
sel2 := DocW().Find(".toclevel-2")
|
|
||||||
b.StartTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
y = sel.IsSelection(sel2)
|
|
||||||
}
|
|
||||||
b.Logf("IsSelection=%v", y)
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkIsNodes(b *testing.B) {
|
|
||||||
var y bool
|
|
||||||
|
|
||||||
b.StopTimer()
|
|
||||||
sel := DocW().Find("li")
|
|
||||||
sel2 := DocW().Find(".toclevel-2")
|
|
||||||
nodes := sel2.Nodes
|
|
||||||
b.StartTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
y = sel.IsNodes(nodes...)
|
|
||||||
}
|
|
||||||
b.Logf("IsNodes=%v", y)
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkHasClass(b *testing.B) {
|
|
||||||
var y bool
|
|
||||||
|
|
||||||
b.StopTimer()
|
|
||||||
sel := DocW().Find("span")
|
|
||||||
b.StartTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
y = sel.HasClass("official")
|
|
||||||
}
|
|
||||||
b.Logf("HasClass=%v", y)
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkContains(b *testing.B) {
|
|
||||||
var y bool
|
|
||||||
|
|
||||||
b.StopTimer()
|
|
||||||
sel := DocW().Find("span.url")
|
|
||||||
sel2 := DocW().Find("a[rel=\"nofollow\"]")
|
|
||||||
node := sel2.Nodes[0]
|
|
||||||
b.StartTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
y = sel.Contains(node)
|
|
||||||
}
|
|
||||||
b.Logf("Contains=%v", y)
|
|
||||||
}
|
|
716
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/bench_traversal_test.go
generated
vendored
716
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/bench_traversal_test.go
generated
vendored
|
@ -1,716 +0,0 @@
|
||||||
package goquery
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func BenchmarkFind(b *testing.B) {
|
|
||||||
var n int
|
|
||||||
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
if n == 0 {
|
|
||||||
n = DocB().Find("dd").Length()
|
|
||||||
|
|
||||||
} else {
|
|
||||||
DocB().Find("dd")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
b.Logf("Find=%d", n)
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkFindWithinSelection(b *testing.B) {
|
|
||||||
var n int
|
|
||||||
|
|
||||||
b.StopTimer()
|
|
||||||
sel := DocW().Find("ul")
|
|
||||||
b.StartTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
if n == 0 {
|
|
||||||
n = sel.Find("a[class]").Length()
|
|
||||||
} else {
|
|
||||||
sel.Find("a[class]")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
b.Logf("FindWithinSelection=%d", n)
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkFindSelection(b *testing.B) {
|
|
||||||
var n int
|
|
||||||
|
|
||||||
b.StopTimer()
|
|
||||||
sel := DocW().Find("ul")
|
|
||||||
sel2 := DocW().Find("span")
|
|
||||||
b.StartTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
if n == 0 {
|
|
||||||
n = sel.FindSelection(sel2).Length()
|
|
||||||
} else {
|
|
||||||
sel.FindSelection(sel2)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
b.Logf("FindSelection=%d", n)
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkFindNodes(b *testing.B) {
|
|
||||||
var n int
|
|
||||||
|
|
||||||
b.StopTimer()
|
|
||||||
sel := DocW().Find("ul")
|
|
||||||
sel2 := DocW().Find("span")
|
|
||||||
nodes := sel2.Nodes
|
|
||||||
b.StartTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
if n == 0 {
|
|
||||||
n = sel.FindNodes(nodes...).Length()
|
|
||||||
} else {
|
|
||||||
sel.FindNodes(nodes...)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
b.Logf("FindNodes=%d", n)
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkContents(b *testing.B) {
|
|
||||||
var n int
|
|
||||||
|
|
||||||
b.StopTimer()
|
|
||||||
sel := DocW().Find(".toclevel-1")
|
|
||||||
b.StartTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
if n == 0 {
|
|
||||||
n = sel.Contents().Length()
|
|
||||||
} else {
|
|
||||||
sel.Contents()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
b.Logf("Contents=%d", n)
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkContentsFiltered(b *testing.B) {
|
|
||||||
var n int
|
|
||||||
|
|
||||||
b.StopTimer()
|
|
||||||
sel := DocW().Find(".toclevel-1")
|
|
||||||
b.StartTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
if n == 0 {
|
|
||||||
n = sel.ContentsFiltered("a[href=\"#Examples\"]").Length()
|
|
||||||
} else {
|
|
||||||
sel.ContentsFiltered("a[href=\"#Examples\"]")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
b.Logf("ContentsFiltered=%d", n)
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkChildren(b *testing.B) {
|
|
||||||
var n int
|
|
||||||
|
|
||||||
b.StopTimer()
|
|
||||||
sel := DocW().Find(".toclevel-2")
|
|
||||||
b.StartTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
if n == 0 {
|
|
||||||
n = sel.Children().Length()
|
|
||||||
} else {
|
|
||||||
sel.Children()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
b.Logf("Children=%d", n)
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkChildrenFiltered(b *testing.B) {
|
|
||||||
var n int
|
|
||||||
|
|
||||||
b.StopTimer()
|
|
||||||
sel := DocW().Find("h3")
|
|
||||||
b.StartTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
if n == 0 {
|
|
||||||
n = sel.ChildrenFiltered(".editsection").Length()
|
|
||||||
} else {
|
|
||||||
sel.ChildrenFiltered(".editsection")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
b.Logf("ChildrenFiltered=%d", n)
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkParent(b *testing.B) {
|
|
||||||
var n int
|
|
||||||
|
|
||||||
b.StopTimer()
|
|
||||||
sel := DocW().Find("li")
|
|
||||||
b.StartTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
if n == 0 {
|
|
||||||
n = sel.Parent().Length()
|
|
||||||
} else {
|
|
||||||
sel.Parent()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
b.Logf("Parent=%d", n)
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkParentFiltered(b *testing.B) {
|
|
||||||
var n int
|
|
||||||
|
|
||||||
b.StopTimer()
|
|
||||||
sel := DocW().Find("li")
|
|
||||||
b.StartTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
if n == 0 {
|
|
||||||
n = sel.ParentFiltered("ul[id]").Length()
|
|
||||||
} else {
|
|
||||||
sel.ParentFiltered("ul[id]")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
b.Logf("ParentFiltered=%d", n)
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkParents(b *testing.B) {
|
|
||||||
var n int
|
|
||||||
|
|
||||||
b.StopTimer()
|
|
||||||
sel := DocW().Find("th a")
|
|
||||||
b.StartTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
if n == 0 {
|
|
||||||
n = sel.Parents().Length()
|
|
||||||
} else {
|
|
||||||
sel.Parents()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
b.Logf("Parents=%d", n)
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkParentsFiltered(b *testing.B) {
|
|
||||||
var n int
|
|
||||||
|
|
||||||
b.StopTimer()
|
|
||||||
sel := DocW().Find("th a")
|
|
||||||
b.StartTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
if n == 0 {
|
|
||||||
n = sel.ParentsFiltered("tr").Length()
|
|
||||||
} else {
|
|
||||||
sel.ParentsFiltered("tr")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
b.Logf("ParentsFiltered=%d", n)
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkParentsUntil(b *testing.B) {
|
|
||||||
var n int
|
|
||||||
|
|
||||||
b.StopTimer()
|
|
||||||
sel := DocW().Find("th a")
|
|
||||||
b.StartTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
if n == 0 {
|
|
||||||
n = sel.ParentsUntil("table").Length()
|
|
||||||
} else {
|
|
||||||
sel.ParentsUntil("table")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
b.Logf("ParentsUntil=%d", n)
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkParentsUntilSelection(b *testing.B) {
|
|
||||||
var n int
|
|
||||||
|
|
||||||
b.StopTimer()
|
|
||||||
sel := DocW().Find("th a")
|
|
||||||
sel2 := DocW().Find("#content")
|
|
||||||
b.StartTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
if n == 0 {
|
|
||||||
n = sel.ParentsUntilSelection(sel2).Length()
|
|
||||||
} else {
|
|
||||||
sel.ParentsUntilSelection(sel2)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
b.Logf("ParentsUntilSelection=%d", n)
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkParentsUntilNodes(b *testing.B) {
|
|
||||||
var n int
|
|
||||||
|
|
||||||
b.StopTimer()
|
|
||||||
sel := DocW().Find("th a")
|
|
||||||
sel2 := DocW().Find("#content")
|
|
||||||
nodes := sel2.Nodes
|
|
||||||
b.StartTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
if n == 0 {
|
|
||||||
n = sel.ParentsUntilNodes(nodes...).Length()
|
|
||||||
} else {
|
|
||||||
sel.ParentsUntilNodes(nodes...)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
b.Logf("ParentsUntilNodes=%d", n)
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkParentsFilteredUntil(b *testing.B) {
|
|
||||||
var n int
|
|
||||||
|
|
||||||
b.StopTimer()
|
|
||||||
sel := DocW().Find(".toclevel-1 a")
|
|
||||||
b.StartTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
if n == 0 {
|
|
||||||
n = sel.ParentsFilteredUntil(":nth-child(1)", "ul").Length()
|
|
||||||
} else {
|
|
||||||
sel.ParentsFilteredUntil(":nth-child(1)", "ul")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
b.Logf("ParentsFilteredUntil=%d", n)
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkParentsFilteredUntilSelection(b *testing.B) {
|
|
||||||
var n int
|
|
||||||
|
|
||||||
b.StopTimer()
|
|
||||||
sel := DocW().Find(".toclevel-1 a")
|
|
||||||
sel2 := DocW().Find("ul")
|
|
||||||
b.StartTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
if n == 0 {
|
|
||||||
n = sel.ParentsFilteredUntilSelection(":nth-child(1)", sel2).Length()
|
|
||||||
} else {
|
|
||||||
sel.ParentsFilteredUntilSelection(":nth-child(1)", sel2)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
b.Logf("ParentsFilteredUntilSelection=%d", n)
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkParentsFilteredUntilNodes(b *testing.B) {
|
|
||||||
var n int
|
|
||||||
|
|
||||||
b.StopTimer()
|
|
||||||
sel := DocW().Find(".toclevel-1 a")
|
|
||||||
sel2 := DocW().Find("ul")
|
|
||||||
nodes := sel2.Nodes
|
|
||||||
b.StartTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
if n == 0 {
|
|
||||||
n = sel.ParentsFilteredUntilNodes(":nth-child(1)", nodes...).Length()
|
|
||||||
} else {
|
|
||||||
sel.ParentsFilteredUntilNodes(":nth-child(1)", nodes...)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
b.Logf("ParentsFilteredUntilNodes=%d", n)
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkSiblings(b *testing.B) {
|
|
||||||
var n int
|
|
||||||
|
|
||||||
b.StopTimer()
|
|
||||||
sel := DocW().Find("ul li:nth-child(1)")
|
|
||||||
b.StartTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
if n == 0 {
|
|
||||||
n = sel.Siblings().Length()
|
|
||||||
} else {
|
|
||||||
sel.Siblings()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
b.Logf("Siblings=%d", n)
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkSiblingsFiltered(b *testing.B) {
|
|
||||||
var n int
|
|
||||||
|
|
||||||
b.StopTimer()
|
|
||||||
sel := DocW().Find("ul li:nth-child(1)")
|
|
||||||
b.StartTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
if n == 0 {
|
|
||||||
n = sel.SiblingsFiltered("[class]").Length()
|
|
||||||
} else {
|
|
||||||
sel.SiblingsFiltered("[class]")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
b.Logf("SiblingsFiltered=%d", n)
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkNext(b *testing.B) {
|
|
||||||
var n int
|
|
||||||
|
|
||||||
b.StopTimer()
|
|
||||||
sel := DocW().Find("li:nth-child(1)")
|
|
||||||
b.StartTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
if n == 0 {
|
|
||||||
n = sel.Next().Length()
|
|
||||||
} else {
|
|
||||||
sel.Next()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
b.Logf("Next=%d", n)
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkNextFiltered(b *testing.B) {
|
|
||||||
var n int
|
|
||||||
|
|
||||||
b.StopTimer()
|
|
||||||
sel := DocW().Find("li:nth-child(1)")
|
|
||||||
b.StartTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
if n == 0 {
|
|
||||||
n = sel.NextFiltered("[class]").Length()
|
|
||||||
} else {
|
|
||||||
sel.NextFiltered("[class]")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
b.Logf("NextFiltered=%d", n)
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkNextAll(b *testing.B) {
|
|
||||||
var n int
|
|
||||||
|
|
||||||
b.StopTimer()
|
|
||||||
sel := DocW().Find("li:nth-child(3)")
|
|
||||||
b.StartTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
if n == 0 {
|
|
||||||
n = sel.NextAll().Length()
|
|
||||||
} else {
|
|
||||||
sel.NextAll()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
b.Logf("NextAll=%d", n)
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkNextAllFiltered(b *testing.B) {
|
|
||||||
var n int
|
|
||||||
|
|
||||||
b.StopTimer()
|
|
||||||
sel := DocW().Find("li:nth-child(3)")
|
|
||||||
b.StartTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
if n == 0 {
|
|
||||||
n = sel.NextAllFiltered("[class]").Length()
|
|
||||||
} else {
|
|
||||||
sel.NextAllFiltered("[class]")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
b.Logf("NextAllFiltered=%d", n)
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkPrev(b *testing.B) {
|
|
||||||
var n int
|
|
||||||
|
|
||||||
b.StopTimer()
|
|
||||||
sel := DocW().Find("li:last-child")
|
|
||||||
b.StartTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
if n == 0 {
|
|
||||||
n = sel.Prev().Length()
|
|
||||||
} else {
|
|
||||||
sel.Prev()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
b.Logf("Prev=%d", n)
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkPrevFiltered(b *testing.B) {
|
|
||||||
var n int
|
|
||||||
|
|
||||||
b.StopTimer()
|
|
||||||
sel := DocW().Find("li:last-child")
|
|
||||||
b.StartTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
if n == 0 {
|
|
||||||
n = sel.PrevFiltered("[class]").Length()
|
|
||||||
} else {
|
|
||||||
sel.PrevFiltered("[class]")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// There is one more Prev li with a class, compared to Next li with a class
|
|
||||||
// (confirmed by looking at the HTML, this is ok)
|
|
||||||
b.Logf("PrevFiltered=%d", n)
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkPrevAll(b *testing.B) {
|
|
||||||
var n int
|
|
||||||
|
|
||||||
b.StopTimer()
|
|
||||||
sel := DocW().Find("li:nth-child(4)")
|
|
||||||
b.StartTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
if n == 0 {
|
|
||||||
n = sel.PrevAll().Length()
|
|
||||||
} else {
|
|
||||||
sel.PrevAll()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
b.Logf("PrevAll=%d", n)
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkPrevAllFiltered(b *testing.B) {
|
|
||||||
var n int
|
|
||||||
|
|
||||||
b.StopTimer()
|
|
||||||
sel := DocW().Find("li:nth-child(4)")
|
|
||||||
b.StartTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
if n == 0 {
|
|
||||||
n = sel.PrevAllFiltered("[class]").Length()
|
|
||||||
} else {
|
|
||||||
sel.PrevAllFiltered("[class]")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
b.Logf("PrevAllFiltered=%d", n)
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkNextUntil(b *testing.B) {
|
|
||||||
var n int
|
|
||||||
|
|
||||||
b.StopTimer()
|
|
||||||
sel := DocW().Find("li:first-child")
|
|
||||||
b.StartTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
if n == 0 {
|
|
||||||
n = sel.NextUntil(":nth-child(4)").Length()
|
|
||||||
} else {
|
|
||||||
sel.NextUntil(":nth-child(4)")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
b.Logf("NextUntil=%d", n)
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkNextUntilSelection(b *testing.B) {
|
|
||||||
var n int
|
|
||||||
|
|
||||||
b.StopTimer()
|
|
||||||
sel := DocW().Find("h2")
|
|
||||||
sel2 := DocW().Find("ul")
|
|
||||||
b.StartTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
if n == 0 {
|
|
||||||
n = sel.NextUntilSelection(sel2).Length()
|
|
||||||
} else {
|
|
||||||
sel.NextUntilSelection(sel2)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
b.Logf("NextUntilSelection=%d", n)
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkNextUntilNodes(b *testing.B) {
|
|
||||||
var n int
|
|
||||||
|
|
||||||
b.StopTimer()
|
|
||||||
sel := DocW().Find("h2")
|
|
||||||
sel2 := DocW().Find("p")
|
|
||||||
nodes := sel2.Nodes
|
|
||||||
b.StartTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
if n == 0 {
|
|
||||||
n = sel.NextUntilNodes(nodes...).Length()
|
|
||||||
} else {
|
|
||||||
sel.NextUntilNodes(nodes...)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
b.Logf("NextUntilNodes=%d", n)
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkPrevUntil(b *testing.B) {
|
|
||||||
var n int
|
|
||||||
|
|
||||||
b.StopTimer()
|
|
||||||
sel := DocW().Find("li:last-child")
|
|
||||||
b.StartTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
if n == 0 {
|
|
||||||
n = sel.PrevUntil(":nth-child(4)").Length()
|
|
||||||
} else {
|
|
||||||
sel.PrevUntil(":nth-child(4)")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
b.Logf("PrevUntil=%d", n)
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkPrevUntilSelection(b *testing.B) {
|
|
||||||
var n int
|
|
||||||
|
|
||||||
b.StopTimer()
|
|
||||||
sel := DocW().Find("h2")
|
|
||||||
sel2 := DocW().Find("ul")
|
|
||||||
b.StartTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
if n == 0 {
|
|
||||||
n = sel.PrevUntilSelection(sel2).Length()
|
|
||||||
} else {
|
|
||||||
sel.PrevUntilSelection(sel2)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
b.Logf("PrevUntilSelection=%d", n)
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkPrevUntilNodes(b *testing.B) {
|
|
||||||
var n int
|
|
||||||
|
|
||||||
b.StopTimer()
|
|
||||||
sel := DocW().Find("h2")
|
|
||||||
sel2 := DocW().Find("p")
|
|
||||||
nodes := sel2.Nodes
|
|
||||||
b.StartTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
if n == 0 {
|
|
||||||
n = sel.PrevUntilNodes(nodes...).Length()
|
|
||||||
} else {
|
|
||||||
sel.PrevUntilNodes(nodes...)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
b.Logf("PrevUntilNodes=%d", n)
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkNextFilteredUntil(b *testing.B) {
|
|
||||||
var n int
|
|
||||||
|
|
||||||
b.StopTimer()
|
|
||||||
sel := DocW().Find("h2")
|
|
||||||
b.StartTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
if n == 0 {
|
|
||||||
n = sel.NextFilteredUntil("p", "div").Length()
|
|
||||||
} else {
|
|
||||||
sel.NextFilteredUntil("p", "div")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
b.Logf("NextFilteredUntil=%d", n)
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkNextFilteredUntilSelection(b *testing.B) {
|
|
||||||
var n int
|
|
||||||
|
|
||||||
b.StopTimer()
|
|
||||||
sel := DocW().Find("h2")
|
|
||||||
sel2 := DocW().Find("div")
|
|
||||||
b.StartTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
if n == 0 {
|
|
||||||
n = sel.NextFilteredUntilSelection("p", sel2).Length()
|
|
||||||
} else {
|
|
||||||
sel.NextFilteredUntilSelection("p", sel2)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
b.Logf("NextFilteredUntilSelection=%d", n)
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkNextFilteredUntilNodes(b *testing.B) {
|
|
||||||
var n int
|
|
||||||
|
|
||||||
b.StopTimer()
|
|
||||||
sel := DocW().Find("h2")
|
|
||||||
sel2 := DocW().Find("div")
|
|
||||||
nodes := sel2.Nodes
|
|
||||||
b.StartTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
if n == 0 {
|
|
||||||
n = sel.NextFilteredUntilNodes("p", nodes...).Length()
|
|
||||||
} else {
|
|
||||||
sel.NextFilteredUntilNodes("p", nodes...)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
b.Logf("NextFilteredUntilNodes=%d", n)
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkPrevFilteredUntil(b *testing.B) {
|
|
||||||
var n int
|
|
||||||
|
|
||||||
b.StopTimer()
|
|
||||||
sel := DocW().Find("h2")
|
|
||||||
b.StartTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
if n == 0 {
|
|
||||||
n = sel.PrevFilteredUntil("p", "div").Length()
|
|
||||||
} else {
|
|
||||||
sel.PrevFilteredUntil("p", "div")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
b.Logf("PrevFilteredUntil=%d", n)
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkPrevFilteredUntilSelection(b *testing.B) {
|
|
||||||
var n int
|
|
||||||
|
|
||||||
b.StopTimer()
|
|
||||||
sel := DocW().Find("h2")
|
|
||||||
sel2 := DocW().Find("div")
|
|
||||||
b.StartTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
if n == 0 {
|
|
||||||
n = sel.PrevFilteredUntilSelection("p", sel2).Length()
|
|
||||||
} else {
|
|
||||||
sel.PrevFilteredUntilSelection("p", sel2)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
b.Logf("PrevFilteredUntilSelection=%d", n)
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkPrevFilteredUntilNodes(b *testing.B) {
|
|
||||||
var n int
|
|
||||||
|
|
||||||
b.StopTimer()
|
|
||||||
sel := DocW().Find("h2")
|
|
||||||
sel2 := DocW().Find("div")
|
|
||||||
nodes := sel2.Nodes
|
|
||||||
b.StartTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
if n == 0 {
|
|
||||||
n = sel.PrevFilteredUntilNodes("p", nodes...).Length()
|
|
||||||
} else {
|
|
||||||
sel.PrevFilteredUntilNodes("p", nodes...)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
b.Logf("PrevFilteredUntilNodes=%d", n)
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkClosest(b *testing.B) {
|
|
||||||
var n int
|
|
||||||
|
|
||||||
b.StopTimer()
|
|
||||||
sel := Doc().Find(".container-fluid")
|
|
||||||
b.StartTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
if n == 0 {
|
|
||||||
n = sel.Closest(".pvk-content").Length()
|
|
||||||
} else {
|
|
||||||
sel.Closest(".pvk-content")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
b.Logf("Closest=%d", n)
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkClosestSelection(b *testing.B) {
|
|
||||||
var n int
|
|
||||||
|
|
||||||
b.StopTimer()
|
|
||||||
sel := Doc().Find(".container-fluid")
|
|
||||||
sel2 := Doc().Find(".pvk-content")
|
|
||||||
b.StartTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
if n == 0 {
|
|
||||||
n = sel.ClosestSelection(sel2).Length()
|
|
||||||
} else {
|
|
||||||
sel.ClosestSelection(sel2)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
b.Logf("ClosestSelection=%d", n)
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkClosestNodes(b *testing.B) {
|
|
||||||
var n int
|
|
||||||
|
|
||||||
b.StopTimer()
|
|
||||||
sel := Doc().Find(".container-fluid")
|
|
||||||
nodes := Doc().Find(".pvk-content").Nodes
|
|
||||||
b.StartTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
if n == 0 {
|
|
||||||
n = sel.ClosestNodes(nodes...).Length()
|
|
||||||
} else {
|
|
||||||
sel.ClosestNodes(nodes...)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
b.Logf("ClosestNodes=%d", n)
|
|
||||||
}
|
|
32
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/example_test.go
generated
vendored
32
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/example_test.go
generated
vendored
|
@ -1,32 +0,0 @@
|
||||||
package goquery
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"log"
|
|
||||||
|
|
||||||
// In real use, this import would be required (not in this example, since it
|
|
||||||
// is part of the goquery package)
|
|
||||||
//"github.com/PuerkitoBio/goquery"
|
|
||||||
)
|
|
||||||
|
|
||||||
// This example scrapes the reviews shown on the home page of metalsucks.net.
|
|
||||||
func ExampleScrape_MetalSucks() {
|
|
||||||
// Load the HTML document (in real use, the type would be *goquery.Document)
|
|
||||||
doc, err := NewDocument("http://metalsucks.net")
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find the review items (the type of the Selection would be *goquery.Selection)
|
|
||||||
doc.Find(".reviews-wrap article .review-rhs").Each(func(i int, s *Selection) {
|
|
||||||
// For each item found, get the band and title
|
|
||||||
band := s.Find("h3").Text()
|
|
||||||
title := s.Find("i").Text()
|
|
||||||
fmt.Printf("Review %d: %s - %s\n", i, band, title)
|
|
||||||
})
|
|
||||||
// To see the output of the Example while running the test suite (go test), simply
|
|
||||||
// remove the leading "x" before Output on the next line. This will cause the
|
|
||||||
// example to fail (all the "real" tests should pass).
|
|
||||||
|
|
||||||
// xOutput: voluntarily fail the Example output.
|
|
||||||
}
|
|
68
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/expand_test.go
generated
vendored
68
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/expand_test.go
generated
vendored
|
@ -1,68 +0,0 @@
|
||||||
package goquery
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestAdd(t *testing.T) {
|
|
||||||
sel := Doc().Find("div.row-fluid").Add("a")
|
|
||||||
assertLength(t, sel.Nodes, 19)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestAddRollback(t *testing.T) {
|
|
||||||
sel := Doc().Find(".pvk-content")
|
|
||||||
sel2 := sel.Add("a").End()
|
|
||||||
assertEqual(t, sel, sel2)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestAddSelection(t *testing.T) {
|
|
||||||
sel := Doc().Find("div.row-fluid")
|
|
||||||
sel2 := Doc().Find("a")
|
|
||||||
sel = sel.AddSelection(sel2)
|
|
||||||
assertLength(t, sel.Nodes, 19)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestAddSelectionNil(t *testing.T) {
|
|
||||||
sel := Doc().Find("div.row-fluid")
|
|
||||||
assertLength(t, sel.Nodes, 9)
|
|
||||||
|
|
||||||
sel = sel.AddSelection(nil)
|
|
||||||
assertLength(t, sel.Nodes, 9)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestAddSelectionRollback(t *testing.T) {
|
|
||||||
sel := Doc().Find(".pvk-content")
|
|
||||||
sel2 := sel.Find("a")
|
|
||||||
sel2 = sel.AddSelection(sel2).End()
|
|
||||||
assertEqual(t, sel, sel2)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestAddNodes(t *testing.T) {
|
|
||||||
sel := Doc().Find("div.pvk-gutter")
|
|
||||||
sel2 := Doc().Find(".pvk-content")
|
|
||||||
sel = sel.AddNodes(sel2.Nodes...)
|
|
||||||
assertLength(t, sel.Nodes, 9)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestAddNodesNone(t *testing.T) {
|
|
||||||
sel := Doc().Find("div.pvk-gutter").AddNodes()
|
|
||||||
assertLength(t, sel.Nodes, 6)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestAddNodesRollback(t *testing.T) {
|
|
||||||
sel := Doc().Find(".pvk-content")
|
|
||||||
sel2 := sel.Find("a")
|
|
||||||
sel2 = sel.AddNodes(sel2.Nodes...).End()
|
|
||||||
assertEqual(t, sel, sel2)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestAndSelf(t *testing.T) {
|
|
||||||
sel := Doc().Find(".span12").Last().AndSelf()
|
|
||||||
assertLength(t, sel.Nodes, 2)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestAndSelfRollback(t *testing.T) {
|
|
||||||
sel := Doc().Find(".pvk-content")
|
|
||||||
sel2 := sel.Find("a").AndSelf().End().End()
|
|
||||||
assertEqual(t, sel, sel2)
|
|
||||||
}
|
|
191
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/filter_test.go
generated
vendored
191
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/filter_test.go
generated
vendored
|
@ -1,191 +0,0 @@
|
||||||
package goquery
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestFilter(t *testing.T) {
|
|
||||||
sel := Doc().Find(".span12").Filter(".alert")
|
|
||||||
assertLength(t, sel.Nodes, 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFilterNone(t *testing.T) {
|
|
||||||
sel := Doc().Find(".span12").Filter(".zzalert")
|
|
||||||
assertLength(t, sel.Nodes, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFilterRollback(t *testing.T) {
|
|
||||||
sel := Doc().Find(".pvk-content")
|
|
||||||
sel2 := sel.Filter(".alert").End()
|
|
||||||
assertEqual(t, sel, sel2)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFilterFunction(t *testing.T) {
|
|
||||||
sel := Doc().Find(".pvk-content").FilterFunction(func(i int, s *Selection) bool {
|
|
||||||
return i > 0
|
|
||||||
})
|
|
||||||
assertLength(t, sel.Nodes, 2)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFilterFunctionRollback(t *testing.T) {
|
|
||||||
sel := Doc().Find(".pvk-content")
|
|
||||||
sel2 := sel.FilterFunction(func(i int, s *Selection) bool {
|
|
||||||
return i > 0
|
|
||||||
}).End()
|
|
||||||
assertEqual(t, sel, sel2)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFilterNode(t *testing.T) {
|
|
||||||
sel := Doc().Find(".pvk-content")
|
|
||||||
sel2 := sel.FilterNodes(sel.Nodes[2])
|
|
||||||
assertLength(t, sel2.Nodes, 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFilterNodeRollback(t *testing.T) {
|
|
||||||
sel := Doc().Find(".pvk-content")
|
|
||||||
sel2 := sel.FilterNodes(sel.Nodes[2]).End()
|
|
||||||
assertEqual(t, sel, sel2)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFilterSelection(t *testing.T) {
|
|
||||||
sel := Doc().Find(".link")
|
|
||||||
sel2 := Doc().Find("a[ng-click]")
|
|
||||||
sel3 := sel.FilterSelection(sel2)
|
|
||||||
assertLength(t, sel3.Nodes, 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFilterSelectionRollback(t *testing.T) {
|
|
||||||
sel := Doc().Find(".link")
|
|
||||||
sel2 := Doc().Find("a[ng-click]")
|
|
||||||
sel2 = sel.FilterSelection(sel2).End()
|
|
||||||
assertEqual(t, sel, sel2)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFilterSelectionNil(t *testing.T) {
|
|
||||||
var sel2 *Selection
|
|
||||||
|
|
||||||
sel := Doc().Find(".link")
|
|
||||||
sel3 := sel.FilterSelection(sel2)
|
|
||||||
assertLength(t, sel3.Nodes, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestNot(t *testing.T) {
|
|
||||||
sel := Doc().Find(".span12").Not(".alert")
|
|
||||||
assertLength(t, sel.Nodes, 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestNotRollback(t *testing.T) {
|
|
||||||
sel := Doc().Find(".span12")
|
|
||||||
sel2 := sel.Not(".alert").End()
|
|
||||||
assertEqual(t, sel, sel2)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestNotNone(t *testing.T) {
|
|
||||||
sel := Doc().Find(".span12").Not(".zzalert")
|
|
||||||
assertLength(t, sel.Nodes, 2)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestNotFunction(t *testing.T) {
|
|
||||||
sel := Doc().Find(".pvk-content").NotFunction(func(i int, s *Selection) bool {
|
|
||||||
return i > 0
|
|
||||||
})
|
|
||||||
assertLength(t, sel.Nodes, 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestNotFunctionRollback(t *testing.T) {
|
|
||||||
sel := Doc().Find(".pvk-content")
|
|
||||||
sel2 := sel.NotFunction(func(i int, s *Selection) bool {
|
|
||||||
return i > 0
|
|
||||||
}).End()
|
|
||||||
assertEqual(t, sel, sel2)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestNotNode(t *testing.T) {
|
|
||||||
sel := Doc().Find(".pvk-content")
|
|
||||||
sel2 := sel.NotNodes(sel.Nodes[2])
|
|
||||||
assertLength(t, sel2.Nodes, 2)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestNotNodeRollback(t *testing.T) {
|
|
||||||
sel := Doc().Find(".pvk-content")
|
|
||||||
sel2 := sel.NotNodes(sel.Nodes[2]).End()
|
|
||||||
assertEqual(t, sel, sel2)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestNotSelection(t *testing.T) {
|
|
||||||
sel := Doc().Find(".link")
|
|
||||||
sel2 := Doc().Find("a[ng-click]")
|
|
||||||
sel3 := sel.NotSelection(sel2)
|
|
||||||
assertLength(t, sel3.Nodes, 6)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestNotSelectionRollback(t *testing.T) {
|
|
||||||
sel := Doc().Find(".link")
|
|
||||||
sel2 := Doc().Find("a[ng-click]")
|
|
||||||
sel2 = sel.NotSelection(sel2).End()
|
|
||||||
assertEqual(t, sel, sel2)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestIntersection(t *testing.T) {
|
|
||||||
sel := Doc().Find(".pvk-gutter")
|
|
||||||
sel2 := Doc().Find("div").Intersection(sel)
|
|
||||||
assertLength(t, sel2.Nodes, 6)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestIntersectionRollback(t *testing.T) {
|
|
||||||
sel := Doc().Find(".pvk-gutter")
|
|
||||||
sel2 := Doc().Find("div")
|
|
||||||
sel2 = sel.Intersection(sel2).End()
|
|
||||||
assertEqual(t, sel, sel2)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestHas(t *testing.T) {
|
|
||||||
sel := Doc().Find(".container-fluid").Has(".center-content")
|
|
||||||
assertLength(t, sel.Nodes, 2)
|
|
||||||
// Has() returns the high-level .container-fluid div, and the one that is the immediate parent of center-content
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestHasRollback(t *testing.T) {
|
|
||||||
sel := Doc().Find(".container-fluid")
|
|
||||||
sel2 := sel.Has(".center-content").End()
|
|
||||||
assertEqual(t, sel, sel2)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestHasNodes(t *testing.T) {
|
|
||||||
sel := Doc().Find(".container-fluid")
|
|
||||||
sel2 := Doc().Find(".center-content")
|
|
||||||
sel = sel.HasNodes(sel2.Nodes...)
|
|
||||||
assertLength(t, sel.Nodes, 2)
|
|
||||||
// Has() returns the high-level .container-fluid div, and the one that is the immediate parent of center-content
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestHasNodesRollback(t *testing.T) {
|
|
||||||
sel := Doc().Find(".container-fluid")
|
|
||||||
sel2 := Doc().Find(".center-content")
|
|
||||||
sel2 = sel.HasNodes(sel2.Nodes...).End()
|
|
||||||
assertEqual(t, sel, sel2)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestHasSelection(t *testing.T) {
|
|
||||||
sel := Doc().Find("p")
|
|
||||||
sel2 := Doc().Find("small")
|
|
||||||
sel = sel.HasSelection(sel2)
|
|
||||||
assertLength(t, sel.Nodes, 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestHasSelectionRollback(t *testing.T) {
|
|
||||||
sel := Doc().Find("p")
|
|
||||||
sel2 := Doc().Find("small")
|
|
||||||
sel2 = sel.HasSelection(sel2).End()
|
|
||||||
assertEqual(t, sel, sel2)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestEnd(t *testing.T) {
|
|
||||||
sel := Doc().Find("p").Has("small").End()
|
|
||||||
assertLength(t, sel.Nodes, 4)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestEndToTop(t *testing.T) {
|
|
||||||
sel := Doc().Find("p").Has("small").End().End().End()
|
|
||||||
assertLength(t, sel.Nodes, 0)
|
|
||||||
}
|
|
88
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/iteration_test.go
generated
vendored
88
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/iteration_test.go
generated
vendored
|
@ -1,88 +0,0 @@
|
||||||
package goquery
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"golang.org/x/net/html"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestEach(t *testing.T) {
|
|
||||||
var cnt int
|
|
||||||
|
|
||||||
sel := Doc().Find(".hero-unit .row-fluid").Each(func(i int, n *Selection) {
|
|
||||||
cnt++
|
|
||||||
t.Logf("At index %v, node %v", i, n.Nodes[0].Data)
|
|
||||||
}).Find("a")
|
|
||||||
|
|
||||||
if cnt != 4 {
|
|
||||||
t.Errorf("Expected Each() to call function 4 times, got %v times.", cnt)
|
|
||||||
}
|
|
||||||
assertLength(t, sel.Nodes, 6)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestEachWithBreak(t *testing.T) {
|
|
||||||
var cnt int
|
|
||||||
|
|
||||||
sel := Doc().Find(".hero-unit .row-fluid").EachWithBreak(func(i int, n *Selection) bool {
|
|
||||||
cnt++
|
|
||||||
t.Logf("At index %v, node %v", i, n.Nodes[0].Data)
|
|
||||||
return false
|
|
||||||
}).Find("a")
|
|
||||||
|
|
||||||
if cnt != 1 {
|
|
||||||
t.Errorf("Expected Each() to call function 1 time, got %v times.", cnt)
|
|
||||||
}
|
|
||||||
assertLength(t, sel.Nodes, 6)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestEachEmptySelection(t *testing.T) {
|
|
||||||
var cnt int
|
|
||||||
|
|
||||||
sel := Doc().Find("zzzz")
|
|
||||||
sel.Each(func(i int, n *Selection) {
|
|
||||||
cnt++
|
|
||||||
})
|
|
||||||
if cnt > 0 {
|
|
||||||
t.Error("Expected Each() to not be called on empty Selection.")
|
|
||||||
}
|
|
||||||
sel2 := sel.Find("div")
|
|
||||||
assertLength(t, sel2.Nodes, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestMap(t *testing.T) {
|
|
||||||
sel := Doc().Find(".pvk-content")
|
|
||||||
vals := sel.Map(func(i int, s *Selection) string {
|
|
||||||
n := s.Get(0)
|
|
||||||
if n.Type == html.ElementNode {
|
|
||||||
return n.Data
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
})
|
|
||||||
for _, v := range vals {
|
|
||||||
if v != "div" {
|
|
||||||
t.Error("Expected Map array result to be all 'div's.")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if len(vals) != 3 {
|
|
||||||
t.Errorf("Expected Map array result to have a length of 3, found %v.", len(vals))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestForRange(t *testing.T) {
|
|
||||||
sel := Doc().Find(".pvk-content")
|
|
||||||
initLen := sel.Length()
|
|
||||||
for i := range sel.Nodes {
|
|
||||||
single := sel.Eq(i)
|
|
||||||
//h, err := single.Html()
|
|
||||||
//if err != nil {
|
|
||||||
// t.Fatal(err)
|
|
||||||
//}
|
|
||||||
//fmt.Println(i, h)
|
|
||||||
if single.Length() != 1 {
|
|
||||||
t.Errorf("%d: expected length of 1, got %d", i, single.Length())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if sel.Length() != initLen {
|
|
||||||
t.Errorf("expected initial selection to still have length %d, got %d", initLen, sel.Length())
|
|
||||||
}
|
|
||||||
}
|
|
453
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/manipulation_test.go
generated
vendored
453
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/manipulation_test.go
generated
vendored
|
@ -1,453 +0,0 @@
|
||||||
package goquery
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
wrapHtml = "<div id=\"ins\">test string<div><p><em><b></b></em></p></div></div>"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestAfter(t *testing.T) {
|
|
||||||
doc := Doc2Clone()
|
|
||||||
doc.Find("#main").After("#nf6")
|
|
||||||
|
|
||||||
assertLength(t, doc.Find("#main #nf6").Nodes, 0)
|
|
||||||
assertLength(t, doc.Find("#foot #nf6").Nodes, 0)
|
|
||||||
assertLength(t, doc.Find("#main + #nf6").Nodes, 1)
|
|
||||||
printSel(t, doc.Selection)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestAfterMany(t *testing.T) {
|
|
||||||
doc := Doc2Clone()
|
|
||||||
doc.Find(".one").After("#nf6")
|
|
||||||
|
|
||||||
assertLength(t, doc.Find("#foot #nf6").Nodes, 1)
|
|
||||||
assertLength(t, doc.Find("#main #nf6").Nodes, 1)
|
|
||||||
assertLength(t, doc.Find(".one + #nf6").Nodes, 2)
|
|
||||||
printSel(t, doc.Selection)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestAfterWithRemoved(t *testing.T) {
|
|
||||||
doc := Doc2Clone()
|
|
||||||
s := doc.Find("#main").Remove()
|
|
||||||
s.After("#nf6")
|
|
||||||
|
|
||||||
assertLength(t, s.Find("#nf6").Nodes, 0)
|
|
||||||
assertLength(t, doc.Find("#nf6").Nodes, 0)
|
|
||||||
printSel(t, doc.Selection)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestAfterSelection(t *testing.T) {
|
|
||||||
doc := Doc2Clone()
|
|
||||||
doc.Find("#main").AfterSelection(doc.Find("#nf1, #nf2"))
|
|
||||||
|
|
||||||
assertLength(t, doc.Find("#main #nf1, #main #nf2").Nodes, 0)
|
|
||||||
assertLength(t, doc.Find("#foot #nf1, #foot #nf2").Nodes, 0)
|
|
||||||
assertLength(t, doc.Find("#main + #nf1, #nf1 + #nf2").Nodes, 2)
|
|
||||||
printSel(t, doc.Selection)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestAfterHtml(t *testing.T) {
|
|
||||||
doc := Doc2Clone()
|
|
||||||
doc.Find("#main").AfterHtml("<strong>new node</strong>")
|
|
||||||
|
|
||||||
assertLength(t, doc.Find("#main + strong").Nodes, 1)
|
|
||||||
printSel(t, doc.Selection)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestAppend(t *testing.T) {
|
|
||||||
doc := Doc2Clone()
|
|
||||||
doc.Find("#main").Append("#nf6")
|
|
||||||
|
|
||||||
assertLength(t, doc.Find("#foot #nf6").Nodes, 0)
|
|
||||||
assertLength(t, doc.Find("#main #nf6").Nodes, 1)
|
|
||||||
printSel(t, doc.Selection)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestAppendBody(t *testing.T) {
|
|
||||||
doc := Doc2Clone()
|
|
||||||
doc.Find("body").Append("#nf6")
|
|
||||||
|
|
||||||
assertLength(t, doc.Find("#foot #nf6").Nodes, 0)
|
|
||||||
assertLength(t, doc.Find("#main #nf6").Nodes, 0)
|
|
||||||
assertLength(t, doc.Find("body > #nf6").Nodes, 1)
|
|
||||||
printSel(t, doc.Selection)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestAppendSelection(t *testing.T) {
|
|
||||||
doc := Doc2Clone()
|
|
||||||
doc.Find("#main").AppendSelection(doc.Find("#nf1, #nf2"))
|
|
||||||
|
|
||||||
assertLength(t, doc.Find("#foot #nf1").Nodes, 0)
|
|
||||||
assertLength(t, doc.Find("#foot #nf2").Nodes, 0)
|
|
||||||
assertLength(t, doc.Find("#main #nf1").Nodes, 1)
|
|
||||||
assertLength(t, doc.Find("#main #nf2").Nodes, 1)
|
|
||||||
printSel(t, doc.Selection)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestAppendSelectionExisting(t *testing.T) {
|
|
||||||
doc := Doc2Clone()
|
|
||||||
doc.Find("#main").AppendSelection(doc.Find("#n1, #n2"))
|
|
||||||
|
|
||||||
assertClass(t, doc.Find("#main :nth-child(1)"), "three")
|
|
||||||
assertClass(t, doc.Find("#main :nth-child(5)"), "one")
|
|
||||||
assertClass(t, doc.Find("#main :nth-child(6)"), "two")
|
|
||||||
printSel(t, doc.Selection)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestAppendClone(t *testing.T) {
|
|
||||||
doc := Doc2Clone()
|
|
||||||
doc.Find("#n1").AppendSelection(doc.Find("#nf1").Clone())
|
|
||||||
|
|
||||||
assertLength(t, doc.Find("#foot #nf1").Nodes, 1)
|
|
||||||
assertLength(t, doc.Find("#main #nf1").Nodes, 1)
|
|
||||||
printSel(t, doc.Selection)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestAppendHtml(t *testing.T) {
|
|
||||||
doc := Doc2Clone()
|
|
||||||
doc.Find("div").AppendHtml("<strong>new node</strong>")
|
|
||||||
|
|
||||||
assertLength(t, doc.Find("strong").Nodes, 14)
|
|
||||||
printSel(t, doc.Selection)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestBefore(t *testing.T) {
|
|
||||||
doc := Doc2Clone()
|
|
||||||
doc.Find("#main").Before("#nf6")
|
|
||||||
|
|
||||||
assertLength(t, doc.Find("#main #nf6").Nodes, 0)
|
|
||||||
assertLength(t, doc.Find("#foot #nf6").Nodes, 0)
|
|
||||||
assertLength(t, doc.Find("body > #nf6:first-child").Nodes, 1)
|
|
||||||
printSel(t, doc.Selection)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestBeforeWithRemoved(t *testing.T) {
|
|
||||||
doc := Doc2Clone()
|
|
||||||
s := doc.Find("#main").Remove()
|
|
||||||
s.Before("#nf6")
|
|
||||||
|
|
||||||
assertLength(t, s.Find("#nf6").Nodes, 0)
|
|
||||||
assertLength(t, doc.Find("#nf6").Nodes, 0)
|
|
||||||
printSel(t, doc.Selection)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestBeforeSelection(t *testing.T) {
|
|
||||||
doc := Doc2Clone()
|
|
||||||
doc.Find("#main").BeforeSelection(doc.Find("#nf1, #nf2"))
|
|
||||||
|
|
||||||
assertLength(t, doc.Find("#main #nf1, #main #nf2").Nodes, 0)
|
|
||||||
assertLength(t, doc.Find("#foot #nf1, #foot #nf2").Nodes, 0)
|
|
||||||
assertLength(t, doc.Find("body > #nf1:first-child, #nf1 + #nf2").Nodes, 2)
|
|
||||||
printSel(t, doc.Selection)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestBeforeHtml(t *testing.T) {
|
|
||||||
doc := Doc2Clone()
|
|
||||||
doc.Find("#main").BeforeHtml("<strong>new node</strong>")
|
|
||||||
|
|
||||||
assertLength(t, doc.Find("body > strong:first-child").Nodes, 1)
|
|
||||||
printSel(t, doc.Selection)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestEmpty(t *testing.T) {
|
|
||||||
doc := Doc2Clone()
|
|
||||||
s := doc.Find("#main").Empty()
|
|
||||||
|
|
||||||
assertLength(t, doc.Find("#main").Children().Nodes, 0)
|
|
||||||
assertLength(t, s.Filter("div").Nodes, 6)
|
|
||||||
printSel(t, doc.Selection)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestPrepend(t *testing.T) {
|
|
||||||
doc := Doc2Clone()
|
|
||||||
doc.Find("#main").Prepend("#nf6")
|
|
||||||
|
|
||||||
assertLength(t, doc.Find("#foot #nf6").Nodes, 0)
|
|
||||||
assertLength(t, doc.Find("#main #nf6:first-child").Nodes, 1)
|
|
||||||
printSel(t, doc.Selection)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestPrependBody(t *testing.T) {
|
|
||||||
doc := Doc2Clone()
|
|
||||||
doc.Find("body").Prepend("#nf6")
|
|
||||||
|
|
||||||
assertLength(t, doc.Find("#foot #nf6").Nodes, 0)
|
|
||||||
assertLength(t, doc.Find("#main #nf6").Nodes, 0)
|
|
||||||
assertLength(t, doc.Find("body > #nf6:first-child").Nodes, 1)
|
|
||||||
printSel(t, doc.Selection)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestPrependSelection(t *testing.T) {
|
|
||||||
doc := Doc2Clone()
|
|
||||||
doc.Find("#main").PrependSelection(doc.Find("#nf1, #nf2"))
|
|
||||||
|
|
||||||
assertLength(t, doc.Find("#foot #nf1").Nodes, 0)
|
|
||||||
assertLength(t, doc.Find("#foot #nf2").Nodes, 0)
|
|
||||||
assertLength(t, doc.Find("#main #nf1:first-child").Nodes, 1)
|
|
||||||
assertLength(t, doc.Find("#main #nf2:nth-child(2)").Nodes, 1)
|
|
||||||
printSel(t, doc.Selection)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestPrependSelectionExisting(t *testing.T) {
|
|
||||||
doc := Doc2Clone()
|
|
||||||
doc.Find("#main").PrependSelection(doc.Find("#n5, #n6"))
|
|
||||||
|
|
||||||
assertClass(t, doc.Find("#main :nth-child(1)"), "five")
|
|
||||||
assertClass(t, doc.Find("#main :nth-child(2)"), "six")
|
|
||||||
assertClass(t, doc.Find("#main :nth-child(5)"), "three")
|
|
||||||
assertClass(t, doc.Find("#main :nth-child(6)"), "four")
|
|
||||||
printSel(t, doc.Selection)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestPrependClone(t *testing.T) {
|
|
||||||
doc := Doc2Clone()
|
|
||||||
doc.Find("#n1").PrependSelection(doc.Find("#nf1").Clone())
|
|
||||||
|
|
||||||
assertLength(t, doc.Find("#foot #nf1:first-child").Nodes, 1)
|
|
||||||
assertLength(t, doc.Find("#main #nf1:first-child").Nodes, 1)
|
|
||||||
printSel(t, doc.Selection)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestPrependHtml(t *testing.T) {
|
|
||||||
doc := Doc2Clone()
|
|
||||||
doc.Find("div").PrependHtml("<strong>new node</strong>")
|
|
||||||
|
|
||||||
assertLength(t, doc.Find("strong:first-child").Nodes, 14)
|
|
||||||
printSel(t, doc.Selection)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestRemove(t *testing.T) {
|
|
||||||
doc := Doc2Clone()
|
|
||||||
doc.Find("#nf1").Remove()
|
|
||||||
|
|
||||||
assertLength(t, doc.Find("#foot #nf1").Nodes, 0)
|
|
||||||
printSel(t, doc.Selection)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestRemoveAll(t *testing.T) {
|
|
||||||
doc := Doc2Clone()
|
|
||||||
doc.Find("*").Remove()
|
|
||||||
|
|
||||||
assertLength(t, doc.Find("*").Nodes, 0)
|
|
||||||
printSel(t, doc.Selection)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestRemoveRoot(t *testing.T) {
|
|
||||||
doc := Doc2Clone()
|
|
||||||
doc.Find("html").Remove()
|
|
||||||
|
|
||||||
assertLength(t, doc.Find("html").Nodes, 0)
|
|
||||||
printSel(t, doc.Selection)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestRemoveFiltered(t *testing.T) {
|
|
||||||
doc := Doc2Clone()
|
|
||||||
nf6 := doc.Find("#nf6")
|
|
||||||
s := doc.Find("div").RemoveFiltered("#nf6")
|
|
||||||
|
|
||||||
assertLength(t, doc.Find("#nf6").Nodes, 0)
|
|
||||||
assertLength(t, s.Nodes, 1)
|
|
||||||
if nf6.Nodes[0] != s.Nodes[0] {
|
|
||||||
t.Error("Removed node does not match original")
|
|
||||||
}
|
|
||||||
printSel(t, doc.Selection)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestReplaceWith(t *testing.T) {
|
|
||||||
doc := Doc2Clone()
|
|
||||||
|
|
||||||
doc.Find("#nf6").ReplaceWith("#main")
|
|
||||||
assertLength(t, doc.Find("#foot #main:last-child").Nodes, 1)
|
|
||||||
printSel(t, doc.Selection)
|
|
||||||
|
|
||||||
doc.Find("#foot").ReplaceWith("#main")
|
|
||||||
assertLength(t, doc.Find("#foot").Nodes, 0)
|
|
||||||
assertLength(t, doc.Find("#main").Nodes, 1)
|
|
||||||
|
|
||||||
printSel(t, doc.Selection)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestReplaceWithHtml(t *testing.T) {
|
|
||||||
doc := Doc2Clone()
|
|
||||||
doc.Find("#main, #foot").ReplaceWithHtml("<div id=\"replace\"></div>")
|
|
||||||
|
|
||||||
assertLength(t, doc.Find("#replace").Nodes, 2)
|
|
||||||
|
|
||||||
printSel(t, doc.Selection)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestReplaceWithSelection(t *testing.T) {
|
|
||||||
doc := Doc2Clone()
|
|
||||||
sel := doc.Find("#nf6").ReplaceWithSelection(doc.Find("#nf5"))
|
|
||||||
|
|
||||||
assertSelectionIs(t, sel, "#nf6")
|
|
||||||
assertLength(t, doc.Find("#nf6").Nodes, 0)
|
|
||||||
assertLength(t, doc.Find("#nf5").Nodes, 1)
|
|
||||||
|
|
||||||
printSel(t, doc.Selection)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestUnwrap(t *testing.T) {
|
|
||||||
doc := Doc2Clone()
|
|
||||||
|
|
||||||
doc.Find("#nf5").Unwrap()
|
|
||||||
assertLength(t, doc.Find("#foot").Nodes, 0)
|
|
||||||
assertLength(t, doc.Find("body > #nf1").Nodes, 1)
|
|
||||||
assertLength(t, doc.Find("body > #nf5").Nodes, 1)
|
|
||||||
|
|
||||||
printSel(t, doc.Selection)
|
|
||||||
|
|
||||||
doc = Doc2Clone()
|
|
||||||
|
|
||||||
doc.Find("#nf5, #n1").Unwrap()
|
|
||||||
assertLength(t, doc.Find("#foot").Nodes, 0)
|
|
||||||
assertLength(t, doc.Find("#main").Nodes, 0)
|
|
||||||
assertLength(t, doc.Find("body > #n1").Nodes, 1)
|
|
||||||
assertLength(t, doc.Find("body > #nf5").Nodes, 1)
|
|
||||||
|
|
||||||
printSel(t, doc.Selection)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestUnwrapBody(t *testing.T) {
|
|
||||||
doc := Doc2Clone()
|
|
||||||
|
|
||||||
doc.Find("#main").Unwrap()
|
|
||||||
assertLength(t, doc.Find("body").Nodes, 1)
|
|
||||||
assertLength(t, doc.Find("body > #main").Nodes, 1)
|
|
||||||
|
|
||||||
printSel(t, doc.Selection)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestUnwrapHead(t *testing.T) {
|
|
||||||
doc := Doc2Clone()
|
|
||||||
|
|
||||||
doc.Find("title").Unwrap()
|
|
||||||
assertLength(t, doc.Find("head").Nodes, 0)
|
|
||||||
assertLength(t, doc.Find("head > title").Nodes, 0)
|
|
||||||
assertLength(t, doc.Find("title").Nodes, 1)
|
|
||||||
|
|
||||||
printSel(t, doc.Selection)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestUnwrapHtml(t *testing.T) {
|
|
||||||
doc := Doc2Clone()
|
|
||||||
|
|
||||||
doc.Find("head").Unwrap()
|
|
||||||
assertLength(t, doc.Find("html").Nodes, 0)
|
|
||||||
assertLength(t, doc.Find("html head").Nodes, 0)
|
|
||||||
assertLength(t, doc.Find("head").Nodes, 1)
|
|
||||||
|
|
||||||
printSel(t, doc.Selection)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestWrap(t *testing.T) {
|
|
||||||
doc := Doc2Clone()
|
|
||||||
doc.Find("#nf1").Wrap("#nf2")
|
|
||||||
nf1 := doc.Find("#foot #nf2 #nf1")
|
|
||||||
assertLength(t, nf1.Nodes, 1)
|
|
||||||
|
|
||||||
nf2 := doc.Find("#nf2")
|
|
||||||
assertLength(t, nf2.Nodes, 2)
|
|
||||||
|
|
||||||
printSel(t, doc.Selection)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestWrapEmpty(t *testing.T) {
|
|
||||||
doc := Doc2Clone()
|
|
||||||
doc.Find("#nf1").Wrap("#doesnt-exist")
|
|
||||||
|
|
||||||
origHtml, _ := Doc2().Html()
|
|
||||||
newHtml, _ := doc.Html()
|
|
||||||
|
|
||||||
if origHtml != newHtml {
|
|
||||||
t.Error("Expected the two documents to be identical.")
|
|
||||||
}
|
|
||||||
|
|
||||||
printSel(t, doc.Selection)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestWrapHtml(t *testing.T) {
|
|
||||||
doc := Doc2Clone()
|
|
||||||
doc.Find(".odd").WrapHtml(wrapHtml)
|
|
||||||
nf2 := doc.Find("#ins #nf2")
|
|
||||||
assertLength(t, nf2.Nodes, 1)
|
|
||||||
printSel(t, doc.Selection)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestWrapSelection(t *testing.T) {
|
|
||||||
doc := Doc2Clone()
|
|
||||||
doc.Find("#nf1").WrapSelection(doc.Find("#nf2"))
|
|
||||||
nf1 := doc.Find("#foot #nf2 #nf1")
|
|
||||||
assertLength(t, nf1.Nodes, 1)
|
|
||||||
|
|
||||||
nf2 := doc.Find("#nf2")
|
|
||||||
assertLength(t, nf2.Nodes, 2)
|
|
||||||
|
|
||||||
printSel(t, doc.Selection)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestWrapAll(t *testing.T) {
|
|
||||||
doc := Doc2Clone()
|
|
||||||
doc.Find(".odd").WrapAll("#nf1")
|
|
||||||
nf1 := doc.Find("#main #nf1")
|
|
||||||
assertLength(t, nf1.Nodes, 1)
|
|
||||||
|
|
||||||
sel := nf1.Find("#n2 ~ #n4 ~ #n6 ~ #nf2 ~ #nf4 ~ #nf6")
|
|
||||||
assertLength(t, sel.Nodes, 1)
|
|
||||||
|
|
||||||
printSel(t, doc.Selection)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestWrapAllHtml(t *testing.T) {
|
|
||||||
doc := Doc2Clone()
|
|
||||||
doc.Find(".odd").WrapAllHtml(wrapHtml)
|
|
||||||
nf1 := doc.Find("#main div#ins div p em b #n2 ~ #n4 ~ #n6 ~ #nf2 ~ #nf4 ~ #nf6")
|
|
||||||
assertLength(t, nf1.Nodes, 1)
|
|
||||||
printSel(t, doc.Selection)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestWrapInnerNoContent(t *testing.T) {
|
|
||||||
doc := Doc2Clone()
|
|
||||||
doc.Find(".one").WrapInner(".two")
|
|
||||||
|
|
||||||
twos := doc.Find(".two")
|
|
||||||
assertLength(t, twos.Nodes, 4)
|
|
||||||
assertLength(t, doc.Find(".one .two").Nodes, 2)
|
|
||||||
|
|
||||||
printSel(t, doc.Selection)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestWrapInnerWithContent(t *testing.T) {
|
|
||||||
doc := Doc3Clone()
|
|
||||||
doc.Find(".one").WrapInner(".two")
|
|
||||||
|
|
||||||
twos := doc.Find(".two")
|
|
||||||
assertLength(t, twos.Nodes, 4)
|
|
||||||
assertLength(t, doc.Find(".one .two").Nodes, 2)
|
|
||||||
|
|
||||||
printSel(t, doc.Selection)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestWrapInnerNoWrapper(t *testing.T) {
|
|
||||||
doc := Doc2Clone()
|
|
||||||
doc.Find(".one").WrapInner(".not-exist")
|
|
||||||
|
|
||||||
twos := doc.Find(".two")
|
|
||||||
assertLength(t, twos.Nodes, 2)
|
|
||||||
assertLength(t, doc.Find(".one").Nodes, 2)
|
|
||||||
assertLength(t, doc.Find(".one .two").Nodes, 0)
|
|
||||||
|
|
||||||
printSel(t, doc.Selection)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestWrapInnerHtml(t *testing.T) {
|
|
||||||
doc := Doc2Clone()
|
|
||||||
doc.Find("#foot").WrapInnerHtml(wrapHtml)
|
|
||||||
|
|
||||||
foot := doc.Find("#foot div#ins div p em b #nf1 ~ #nf2 ~ #nf3")
|
|
||||||
assertLength(t, foot.Nodes, 1)
|
|
||||||
|
|
||||||
printSel(t, doc.Selection)
|
|
||||||
}
|
|
252
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/property_test.go
generated
vendored
252
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/property_test.go
generated
vendored
|
@ -1,252 +0,0 @@
|
||||||
package goquery
|
|
||||||
|
|
||||||
import (
|
|
||||||
"regexp"
|
|
||||||
"strings"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestAttrExists(t *testing.T) {
|
|
||||||
if val, ok := Doc().Find("a").Attr("href"); !ok {
|
|
||||||
t.Error("Expected a value for the href attribute.")
|
|
||||||
} else {
|
|
||||||
t.Logf("Href of first anchor: %v.", val)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestAttrOr(t *testing.T) {
|
|
||||||
if val := Doc().Find("a").AttrOr("fake-attribute", "alternative"); val != "alternative" {
|
|
||||||
t.Error("Expected an alternative value for 'fake-attribute' attribute.")
|
|
||||||
} else {
|
|
||||||
t.Logf("Value returned for not existing attribute: %v.", val)
|
|
||||||
}
|
|
||||||
if val := Doc().Find("zz").AttrOr("fake-attribute", "alternative"); val != "alternative" {
|
|
||||||
t.Error("Expected an alternative value for 'fake-attribute' on an empty selection.")
|
|
||||||
} else {
|
|
||||||
t.Logf("Value returned for empty selection: %v.", val)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestAttrNotExist(t *testing.T) {
|
|
||||||
if val, ok := Doc().Find("div.row-fluid").Attr("href"); ok {
|
|
||||||
t.Errorf("Expected no value for the href attribute, got %v.", val)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestRemoveAttr(t *testing.T) {
|
|
||||||
sel := Doc2Clone().Find("div")
|
|
||||||
|
|
||||||
sel.RemoveAttr("id")
|
|
||||||
|
|
||||||
_, ok := sel.Attr("id")
|
|
||||||
if ok {
|
|
||||||
t.Error("Expected there to be no id attributes set")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSetAttr(t *testing.T) {
|
|
||||||
sel := Doc2Clone().Find("#main")
|
|
||||||
|
|
||||||
sel.SetAttr("id", "not-main")
|
|
||||||
|
|
||||||
val, ok := sel.Attr("id")
|
|
||||||
if !ok {
|
|
||||||
t.Error("Expected an id attribute on main")
|
|
||||||
}
|
|
||||||
|
|
||||||
if val != "not-main" {
|
|
||||||
t.Errorf("Expected an attribute id to be not-main, got %s", val)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSetAttr2(t *testing.T) {
|
|
||||||
sel := Doc2Clone().Find("#main")
|
|
||||||
|
|
||||||
sel.SetAttr("foo", "bar")
|
|
||||||
|
|
||||||
val, ok := sel.Attr("foo")
|
|
||||||
if !ok {
|
|
||||||
t.Error("Expected an 'foo' attribute on main")
|
|
||||||
}
|
|
||||||
|
|
||||||
if val != "bar" {
|
|
||||||
t.Errorf("Expected an attribute 'foo' to be 'bar', got '%s'", val)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestText(t *testing.T) {
|
|
||||||
txt := Doc().Find("h1").Text()
|
|
||||||
if strings.Trim(txt, " \n\r\t") != "Provok.in" {
|
|
||||||
t.Errorf("Expected text to be Provok.in, found %s.", txt)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestText2(t *testing.T) {
|
|
||||||
txt := Doc().Find(".hero-unit .container-fluid .row-fluid:nth-child(1)").Text()
|
|
||||||
if ok, e := regexp.MatchString(`^\s+Provok\.in\s+Prove your point.\s+$`, txt); !ok || e != nil {
|
|
||||||
t.Errorf("Expected text to be Provok.in Prove your point., found %s.", txt)
|
|
||||||
if e != nil {
|
|
||||||
t.Logf("Error: %s.", e.Error())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestText3(t *testing.T) {
|
|
||||||
txt := Doc().Find(".pvk-gutter").First().Text()
|
|
||||||
// There's an character in there...
|
|
||||||
if ok, e := regexp.MatchString(`^[\s\x{00A0}]+$`, txt); !ok || e != nil {
|
|
||||||
t.Errorf("Expected spaces, found <%v>.", txt)
|
|
||||||
if e != nil {
|
|
||||||
t.Logf("Error: %s.", e.Error())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestHtml(t *testing.T) {
|
|
||||||
txt, e := Doc().Find("h1").Html()
|
|
||||||
if e != nil {
|
|
||||||
t.Errorf("Error: %s.", e)
|
|
||||||
}
|
|
||||||
|
|
||||||
if ok, e := regexp.MatchString(`^\s*<a href="/">Provok<span class="green">\.</span><span class="red">i</span>n</a>\s*$`, txt); !ok || e != nil {
|
|
||||||
t.Errorf("Unexpected HTML content, found %s.", txt)
|
|
||||||
if e != nil {
|
|
||||||
t.Logf("Error: %s.", e.Error())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestNbsp(t *testing.T) {
|
|
||||||
src := `<p>Some text</p>`
|
|
||||||
d, err := NewDocumentFromReader(strings.NewReader(src))
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
txt := d.Find("p").Text()
|
|
||||||
ix := strings.Index(txt, "\u00a0")
|
|
||||||
if ix != 4 {
|
|
||||||
t.Errorf("Text: expected a non-breaking space at index 4, got %d", ix)
|
|
||||||
}
|
|
||||||
|
|
||||||
h, err := d.Find("p").Html()
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
ix = strings.Index(h, "\u00a0")
|
|
||||||
if ix != 4 {
|
|
||||||
t.Errorf("Html: expected a non-breaking space at index 4, got %d", ix)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestAddClass(t *testing.T) {
|
|
||||||
sel := Doc2Clone().Find("#main")
|
|
||||||
sel.AddClass("main main main")
|
|
||||||
|
|
||||||
// Make sure that class was only added once
|
|
||||||
if a, ok := sel.Attr("class"); !ok || a != "main" {
|
|
||||||
t.Error("Expected #main to have class main")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestAddClassSimilar(t *testing.T) {
|
|
||||||
sel := Doc2Clone().Find("#nf5")
|
|
||||||
sel.AddClass("odd")
|
|
||||||
|
|
||||||
assertClass(t, sel, "odd")
|
|
||||||
assertClass(t, sel, "odder")
|
|
||||||
printSel(t, sel.Parent())
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestAddEmptyClass(t *testing.T) {
|
|
||||||
sel := Doc2Clone().Find("#main")
|
|
||||||
sel.AddClass("")
|
|
||||||
|
|
||||||
// Make sure that class was only added once
|
|
||||||
if a, ok := sel.Attr("class"); ok {
|
|
||||||
t.Errorf("Expected #main to not to have a class, have: %s", a)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestAddClasses(t *testing.T) {
|
|
||||||
sel := Doc2Clone().Find("#main")
|
|
||||||
sel.AddClass("a b")
|
|
||||||
|
|
||||||
// Make sure that class was only added once
|
|
||||||
if !sel.HasClass("a") || !sel.HasClass("b") {
|
|
||||||
t.Errorf("#main does not have classes")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestHasClass(t *testing.T) {
|
|
||||||
sel := Doc().Find("div")
|
|
||||||
if !sel.HasClass("span12") {
|
|
||||||
t.Error("Expected at least one div to have class span12.")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestHasClassNone(t *testing.T) {
|
|
||||||
sel := Doc().Find("h2")
|
|
||||||
if sel.HasClass("toto") {
|
|
||||||
t.Error("Expected h1 to have no class.")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestHasClassNotFirst(t *testing.T) {
|
|
||||||
sel := Doc().Find(".alert")
|
|
||||||
if !sel.HasClass("alert-error") {
|
|
||||||
t.Error("Expected .alert to also have class .alert-error.")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestRemoveClass(t *testing.T) {
|
|
||||||
sel := Doc2Clone().Find("#nf1")
|
|
||||||
sel.RemoveClass("one row")
|
|
||||||
|
|
||||||
if !sel.HasClass("even") || sel.HasClass("one") || sel.HasClass("row") {
|
|
||||||
classes, _ := sel.Attr("class")
|
|
||||||
t.Error("Expected #nf1 to have class even, has ", classes)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestRemoveClassSimilar(t *testing.T) {
|
|
||||||
sel := Doc2Clone().Find("#nf5, #nf6")
|
|
||||||
assertLength(t, sel.Nodes, 2)
|
|
||||||
|
|
||||||
sel.RemoveClass("odd")
|
|
||||||
assertClass(t, sel.Eq(0), "odder")
|
|
||||||
printSel(t, sel)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestRemoveAllClasses(t *testing.T) {
|
|
||||||
sel := Doc2Clone().Find("#nf1")
|
|
||||||
sel.RemoveClass()
|
|
||||||
|
|
||||||
if a, ok := sel.Attr("class"); ok {
|
|
||||||
t.Error("All classes were not removed, has ", a)
|
|
||||||
}
|
|
||||||
|
|
||||||
sel = Doc2Clone().Find("#main")
|
|
||||||
sel.RemoveClass()
|
|
||||||
if a, ok := sel.Attr("class"); ok {
|
|
||||||
t.Error("All classes were not removed, has ", a)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestToggleClass(t *testing.T) {
|
|
||||||
sel := Doc2Clone().Find("#nf1")
|
|
||||||
|
|
||||||
sel.ToggleClass("one")
|
|
||||||
if sel.HasClass("one") {
|
|
||||||
t.Error("Expected #nf1 to not have class one")
|
|
||||||
}
|
|
||||||
|
|
||||||
sel.ToggleClass("one")
|
|
||||||
if !sel.HasClass("one") {
|
|
||||||
t.Error("Expected #nf1 to have class one")
|
|
||||||
}
|
|
||||||
|
|
||||||
sel.ToggleClass("one even row")
|
|
||||||
if a, ok := sel.Attr("class"); ok {
|
|
||||||
t.Errorf("Expected #nf1 to have no classes, have %q", a)
|
|
||||||
}
|
|
||||||
}
|
|
96
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/query_test.go
generated
vendored
96
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/query_test.go
generated
vendored
|
@ -1,96 +0,0 @@
|
||||||
package goquery
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestIs(t *testing.T) {
|
|
||||||
sel := Doc().Find(".footer p:nth-child(1)")
|
|
||||||
if !sel.Is("p") {
|
|
||||||
t.Error("Expected .footer p:nth-child(1) to be p.")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestIsPositional(t *testing.T) {
|
|
||||||
sel := Doc().Find(".footer p:nth-child(2)")
|
|
||||||
if !sel.Is("p:nth-child(2)") {
|
|
||||||
t.Error("Expected .footer p:nth-child(2) to be p:nth-child(2).")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestIsPositionalNot(t *testing.T) {
|
|
||||||
sel := Doc().Find(".footer p:nth-child(1)")
|
|
||||||
if sel.Is("p:nth-child(2)") {
|
|
||||||
t.Error("Expected .footer p:nth-child(1) NOT to be p:nth-child(2).")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestIsFunction(t *testing.T) {
|
|
||||||
ok := Doc().Find("div").IsFunction(func(i int, s *Selection) bool {
|
|
||||||
return s.HasClass("container-fluid")
|
|
||||||
})
|
|
||||||
|
|
||||||
if !ok {
|
|
||||||
t.Error("Expected some div to have a container-fluid class.")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestIsFunctionRollback(t *testing.T) {
|
|
||||||
ok := Doc().Find("div").IsFunction(func(i int, s *Selection) bool {
|
|
||||||
return s.HasClass("container-fluid")
|
|
||||||
})
|
|
||||||
|
|
||||||
if !ok {
|
|
||||||
t.Error("Expected some div to have a container-fluid class.")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestIsSelection(t *testing.T) {
|
|
||||||
sel := Doc().Find("div")
|
|
||||||
sel2 := Doc().Find(".pvk-gutter")
|
|
||||||
|
|
||||||
if !sel.IsSelection(sel2) {
|
|
||||||
t.Error("Expected some div to have a pvk-gutter class.")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestIsSelectionNot(t *testing.T) {
|
|
||||||
sel := Doc().Find("div")
|
|
||||||
sel2 := Doc().Find("a")
|
|
||||||
|
|
||||||
if sel.IsSelection(sel2) {
|
|
||||||
t.Error("Expected some div NOT to be an anchor.")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestIsNodes(t *testing.T) {
|
|
||||||
sel := Doc().Find("div")
|
|
||||||
sel2 := Doc().Find(".footer")
|
|
||||||
|
|
||||||
if !sel.IsNodes(sel2.Nodes[0]) {
|
|
||||||
t.Error("Expected some div to have a footer class.")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestDocContains(t *testing.T) {
|
|
||||||
sel := Doc().Find("h1")
|
|
||||||
if !Doc().Contains(sel.Nodes[0]) {
|
|
||||||
t.Error("Expected document to contain H1 tag.")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSelContains(t *testing.T) {
|
|
||||||
sel := Doc().Find(".row-fluid")
|
|
||||||
sel2 := Doc().Find("a[ng-click]")
|
|
||||||
if !sel.Contains(sel2.Nodes[0]) {
|
|
||||||
t.Error("Expected .row-fluid to contain a[ng-click] tag.")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSelNotContains(t *testing.T) {
|
|
||||||
sel := Doc().Find("a.link")
|
|
||||||
sel2 := Doc().Find("span")
|
|
||||||
if sel.Contains(sel2.Nodes[0]) {
|
|
||||||
t.Error("Expected a.link to NOT contain span tag.")
|
|
||||||
}
|
|
||||||
}
|
|
855
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/testdata/gotesting.html
generated
vendored
855
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/testdata/gotesting.html
generated
vendored
|
@ -1,855 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
|
||||||
|
|
||||||
<title>testing - The Go Programming Language</title>
|
|
||||||
|
|
||||||
<link type="text/css" rel="stylesheet" href="/doc/style.css">
|
|
||||||
<script type="text/javascript" src="/doc/godocs.js"></script>
|
|
||||||
|
|
||||||
<link rel="search" type="application/opensearchdescription+xml" title="godoc" href="/opensearch.xml" />
|
|
||||||
|
|
||||||
<script type="text/javascript">
|
|
||||||
var _gaq = _gaq || [];
|
|
||||||
_gaq.push(["_setAccount", "UA-11222381-2"]);
|
|
||||||
_gaq.push(["_trackPageview"]);
|
|
||||||
</script>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
|
|
||||||
<div id="topbar"><div class="container wide">
|
|
||||||
|
|
||||||
<form method="GET" action="/search">
|
|
||||||
<div id="menu">
|
|
||||||
<a href="/doc/">Documents</a>
|
|
||||||
<a href="/ref/">References</a>
|
|
||||||
<a href="/pkg/">Packages</a>
|
|
||||||
<a href="/project/">The Project</a>
|
|
||||||
<a href="/help/">Help</a>
|
|
||||||
<input type="text" id="search" name="q" class="inactive" value="Search">
|
|
||||||
</div>
|
|
||||||
<div id="heading"><a href="/">The Go Programming Language</a></div>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
</div></div>
|
|
||||||
|
|
||||||
<div id="page" class="wide">
|
|
||||||
|
|
||||||
|
|
||||||
<div id="plusone"><g:plusone size="small" annotation="none"></g:plusone></div>
|
|
||||||
<h1>Package testing</h1>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div id="nav"></div>
|
|
||||||
|
|
||||||
|
|
||||||
<!--
|
|
||||||
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.
|
|
||||||
-->
|
|
||||||
|
|
||||||
|
|
||||||
<div id="short-nav">
|
|
||||||
<dl>
|
|
||||||
<dd><code>import "testing"</code></dd>
|
|
||||||
</dl>
|
|
||||||
<dl>
|
|
||||||
<dd><a href="#overview" class="overviewLink">Overview</a></dd>
|
|
||||||
<dd><a href="#index">Index</a></dd>
|
|
||||||
|
|
||||||
|
|
||||||
<dd><a href="#subdirectories">Subdirectories</a></dd>
|
|
||||||
|
|
||||||
</dl>
|
|
||||||
</div>
|
|
||||||
<!-- The package's Name is printed as title by the top-level template -->
|
|
||||||
<div id="overview" class="toggleVisible">
|
|
||||||
<div class="collapsed">
|
|
||||||
<h2 class="toggleButton" title="Click to show Overview section">Overview ▹</h2>
|
|
||||||
</div>
|
|
||||||
<div class="expanded">
|
|
||||||
<h2 class="toggleButton" title="Click to hide Overview section">Overview ▾</h2>
|
|
||||||
<p>
|
|
||||||
Package testing provides support for automated testing of Go packages.
|
|
||||||
It is intended to be used in concert with the “go test” command, which automates
|
|
||||||
execution of any function of the form
|
|
||||||
</p>
|
|
||||||
<pre>func TestXxx(*testing.T)
|
|
||||||
</pre>
|
|
||||||
<p>
|
|
||||||
where Xxx can be any alphanumeric string (but the first letter must not be in
|
|
||||||
[a-z]) and serves to identify the test routine.
|
|
||||||
These TestXxx routines should be declared within the package they are testing.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
Functions of the form
|
|
||||||
</p>
|
|
||||||
<pre>func BenchmarkXxx(*testing.B)
|
|
||||||
</pre>
|
|
||||||
<p>
|
|
||||||
are considered benchmarks, and are executed by the "go test" command when
|
|
||||||
the -test.bench flag is provided.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
A sample benchmark function looks like this:
|
|
||||||
</p>
|
|
||||||
<pre>func BenchmarkHello(b *testing.B) {
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
fmt.Sprintf("hello")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</pre>
|
|
||||||
<p>
|
|
||||||
The benchmark package will vary b.N until the benchmark function lasts
|
|
||||||
long enough to be timed reliably. The output
|
|
||||||
</p>
|
|
||||||
<pre>testing.BenchmarkHello 10000000 282 ns/op
|
|
||||||
</pre>
|
|
||||||
<p>
|
|
||||||
means that the loop ran 10000000 times at a speed of 282 ns per loop.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
If a benchmark needs some expensive setup before running, the timer
|
|
||||||
may be stopped:
|
|
||||||
</p>
|
|
||||||
<pre>func BenchmarkBigLen(b *testing.B) {
|
|
||||||
b.StopTimer()
|
|
||||||
big := NewBig()
|
|
||||||
b.StartTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
big.Len()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</pre>
|
|
||||||
<p>
|
|
||||||
The package also runs and verifies example code. Example functions may
|
|
||||||
include a concluding comment that begins with "Output:" and is compared with
|
|
||||||
the standard output of the function when the tests are run, as in these
|
|
||||||
examples of an example:
|
|
||||||
</p>
|
|
||||||
<pre>func ExampleHello() {
|
|
||||||
fmt.Println("hello")
|
|
||||||
// Output: hello
|
|
||||||
}
|
|
||||||
|
|
||||||
func ExampleSalutations() {
|
|
||||||
fmt.Println("hello, and")
|
|
||||||
fmt.Println("goodbye")
|
|
||||||
// Output:
|
|
||||||
// hello, and
|
|
||||||
// goodbye
|
|
||||||
}
|
|
||||||
</pre>
|
|
||||||
<p>
|
|
||||||
Example functions without output comments are compiled but not executed.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
The naming convention to declare examples for a function F, a type T and
|
|
||||||
method M on type T are:
|
|
||||||
</p>
|
|
||||||
<pre>func ExampleF() { ... }
|
|
||||||
func ExampleT() { ... }
|
|
||||||
func ExampleT_M() { ... }
|
|
||||||
</pre>
|
|
||||||
<p>
|
|
||||||
Multiple example functions for a type/function/method may be provided by
|
|
||||||
appending a distinct suffix to the name. The suffix must start with a
|
|
||||||
lower-case letter.
|
|
||||||
</p>
|
|
||||||
<pre>func ExampleF_suffix() { ... }
|
|
||||||
func ExampleT_suffix() { ... }
|
|
||||||
func ExampleT_M_suffix() { ... }
|
|
||||||
</pre>
|
|
||||||
<p>
|
|
||||||
The entire test file is presented as the example when it contains a single
|
|
||||||
example function, at least one other function, type, variable, or constant
|
|
||||||
declaration, and no test or benchmark functions.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<h2 id="index">Index</h2>
|
|
||||||
<!-- Table of contents for API; must be named manual-nav to turn off auto nav. -->
|
|
||||||
<div id="manual-nav">
|
|
||||||
<dl>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<dd><a href="#Main">func Main(matchString func(pat, str string) (bool, error), tests []InternalTest, benchmarks []InternalBenchmark, examples []InternalExample)</a></dd>
|
|
||||||
|
|
||||||
|
|
||||||
<dd><a href="#RunBenchmarks">func RunBenchmarks(matchString func(pat, str string) (bool, error), benchmarks []InternalBenchmark)</a></dd>
|
|
||||||
|
|
||||||
|
|
||||||
<dd><a href="#RunExamples">func RunExamples(matchString func(pat, str string) (bool, error), examples []InternalExample) (ok bool)</a></dd>
|
|
||||||
|
|
||||||
|
|
||||||
<dd><a href="#RunTests">func RunTests(matchString func(pat, str string) (bool, error), tests []InternalTest) (ok bool)</a></dd>
|
|
||||||
|
|
||||||
|
|
||||||
<dd><a href="#Short">func Short() bool</a></dd>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<dd><a href="#B">type B</a></dd>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<dd> <a href="#B.Error">func (c *B) Error(args ...interface{})</a></dd>
|
|
||||||
|
|
||||||
|
|
||||||
<dd> <a href="#B.Errorf">func (c *B) Errorf(format string, args ...interface{})</a></dd>
|
|
||||||
|
|
||||||
|
|
||||||
<dd> <a href="#B.Fail">func (c *B) Fail()</a></dd>
|
|
||||||
|
|
||||||
|
|
||||||
<dd> <a href="#B.FailNow">func (c *B) FailNow()</a></dd>
|
|
||||||
|
|
||||||
|
|
||||||
<dd> <a href="#B.Failed">func (c *B) Failed() bool</a></dd>
|
|
||||||
|
|
||||||
|
|
||||||
<dd> <a href="#B.Fatal">func (c *B) Fatal(args ...interface{})</a></dd>
|
|
||||||
|
|
||||||
|
|
||||||
<dd> <a href="#B.Fatalf">func (c *B) Fatalf(format string, args ...interface{})</a></dd>
|
|
||||||
|
|
||||||
|
|
||||||
<dd> <a href="#B.Log">func (c *B) Log(args ...interface{})</a></dd>
|
|
||||||
|
|
||||||
|
|
||||||
<dd> <a href="#B.Logf">func (c *B) Logf(format string, args ...interface{})</a></dd>
|
|
||||||
|
|
||||||
|
|
||||||
<dd> <a href="#B.ResetTimer">func (b *B) ResetTimer()</a></dd>
|
|
||||||
|
|
||||||
|
|
||||||
<dd> <a href="#B.SetBytes">func (b *B) SetBytes(n int64)</a></dd>
|
|
||||||
|
|
||||||
|
|
||||||
<dd> <a href="#B.StartTimer">func (b *B) StartTimer()</a></dd>
|
|
||||||
|
|
||||||
|
|
||||||
<dd> <a href="#B.StopTimer">func (b *B) StopTimer()</a></dd>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<dd><a href="#BenchmarkResult">type BenchmarkResult</a></dd>
|
|
||||||
|
|
||||||
|
|
||||||
<dd> <a href="#Benchmark">func Benchmark(f func(b *B)) BenchmarkResult</a></dd>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<dd> <a href="#BenchmarkResult.NsPerOp">func (r BenchmarkResult) NsPerOp() int64</a></dd>
|
|
||||||
|
|
||||||
|
|
||||||
<dd> <a href="#BenchmarkResult.String">func (r BenchmarkResult) String() string</a></dd>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<dd><a href="#InternalBenchmark">type InternalBenchmark</a></dd>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<dd><a href="#InternalExample">type InternalExample</a></dd>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<dd><a href="#InternalTest">type InternalTest</a></dd>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<dd><a href="#T">type T</a></dd>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<dd> <a href="#T.Error">func (c *T) Error(args ...interface{})</a></dd>
|
|
||||||
|
|
||||||
|
|
||||||
<dd> <a href="#T.Errorf">func (c *T) Errorf(format string, args ...interface{})</a></dd>
|
|
||||||
|
|
||||||
|
|
||||||
<dd> <a href="#T.Fail">func (c *T) Fail()</a></dd>
|
|
||||||
|
|
||||||
|
|
||||||
<dd> <a href="#T.FailNow">func (c *T) FailNow()</a></dd>
|
|
||||||
|
|
||||||
|
|
||||||
<dd> <a href="#T.Failed">func (c *T) Failed() bool</a></dd>
|
|
||||||
|
|
||||||
|
|
||||||
<dd> <a href="#T.Fatal">func (c *T) Fatal(args ...interface{})</a></dd>
|
|
||||||
|
|
||||||
|
|
||||||
<dd> <a href="#T.Fatalf">func (c *T) Fatalf(format string, args ...interface{})</a></dd>
|
|
||||||
|
|
||||||
|
|
||||||
<dd> <a href="#T.Log">func (c *T) Log(args ...interface{})</a></dd>
|
|
||||||
|
|
||||||
|
|
||||||
<dd> <a href="#T.Logf">func (c *T) Logf(format string, args ...interface{})</a></dd>
|
|
||||||
|
|
||||||
|
|
||||||
<dd> <a href="#T.Parallel">func (t *T) Parallel()</a></dd>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h4>Package files</h4>
|
|
||||||
<p>
|
|
||||||
<span style="font-size:90%">
|
|
||||||
|
|
||||||
<a href="/src/pkg/testing/benchmark.go">benchmark.go</a>
|
|
||||||
|
|
||||||
<a href="/src/pkg/testing/example.go">example.go</a>
|
|
||||||
|
|
||||||
<a href="/src/pkg/testing/testing.go">testing.go</a>
|
|
||||||
|
|
||||||
</span>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h2 id="Main">func <a href="/src/pkg/testing/testing.go?s=9750:9890#L268">Main</a></h2>
|
|
||||||
<pre>func Main(matchString func(pat, str string) (bool, error), tests []InternalTest, benchmarks []InternalBenchmark, examples []InternalExample)</pre>
|
|
||||||
<p>
|
|
||||||
An internal function but exported because it is cross-package; part of the implementation
|
|
||||||
of the "go test" command.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h2 id="RunBenchmarks">func <a href="/src/pkg/testing/benchmark.go?s=5365:5464#L207">RunBenchmarks</a></h2>
|
|
||||||
<pre>func RunBenchmarks(matchString func(pat, str string) (bool, error), benchmarks []InternalBenchmark)</pre>
|
|
||||||
<p>
|
|
||||||
An internal function but exported because it is cross-package; part of the implementation
|
|
||||||
of the "go test" command.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h2 id="RunExamples">func <a href="/src/pkg/testing/example.go?s=314:417#L12">RunExamples</a></h2>
|
|
||||||
<pre>func RunExamples(matchString func(pat, str string) (bool, error), examples []InternalExample) (ok bool)</pre>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h2 id="RunTests">func <a href="/src/pkg/testing/testing.go?s=10486:10580#L297">RunTests</a></h2>
|
|
||||||
<pre>func RunTests(matchString func(pat, str string) (bool, error), tests []InternalTest) (ok bool)</pre>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h2 id="Short">func <a href="/src/pkg/testing/testing.go?s=4859:4876#L117">Short</a></h2>
|
|
||||||
<pre>func Short() bool</pre>
|
|
||||||
<p>
|
|
||||||
Short reports whether the -test.short flag is set.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h2 id="B">type <a href="/src/pkg/testing/benchmark.go?s=743:872#L17">B</a></h2>
|
|
||||||
<pre>type B struct {
|
|
||||||
N int
|
|
||||||
<span class="comment">// contains filtered or unexported fields</span>
|
|
||||||
}</pre>
|
|
||||||
<p>
|
|
||||||
B is a type passed to Benchmark functions to manage benchmark
|
|
||||||
timing and to specify the number of iterations to run.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h3 id="B.Error">func (*B) <a href="/src/pkg/testing/testing.go?s=8110:8153#L209">Error</a></h3>
|
|
||||||
<pre>func (c *B) Error(args ...interface{})</pre>
|
|
||||||
<p>
|
|
||||||
Error is equivalent to Log() followed by Fail().
|
|
||||||
</p>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h3 id="B.Errorf">func (*B) <a href="/src/pkg/testing/testing.go?s=8253:8312#L215">Errorf</a></h3>
|
|
||||||
<pre>func (c *B) Errorf(format string, args ...interface{})</pre>
|
|
||||||
<p>
|
|
||||||
Errorf is equivalent to Logf() followed by Fail().
|
|
||||||
</p>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h3 id="B.Fail">func (*B) <a href="/src/pkg/testing/testing.go?s=6270:6293#L163">Fail</a></h3>
|
|
||||||
<pre>func (c *B) Fail()</pre>
|
|
||||||
<p>
|
|
||||||
Fail marks the function as having failed but continues execution.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h3 id="B.FailNow">func (*B) <a href="/src/pkg/testing/testing.go?s=6548:6574#L170">FailNow</a></h3>
|
|
||||||
<pre>func (c *B) FailNow()</pre>
|
|
||||||
<p>
|
|
||||||
FailNow marks the function as having failed and stops its execution.
|
|
||||||
Execution will continue at the next test or benchmark.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h3 id="B.Failed">func (*B) <a href="/src/pkg/testing/testing.go?s=6366:6396#L166">Failed</a></h3>
|
|
||||||
<pre>func (c *B) Failed() bool</pre>
|
|
||||||
<p>
|
|
||||||
Failed returns whether the function has failed.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h3 id="B.Fatal">func (*B) <a href="/src/pkg/testing/testing.go?s=8420:8463#L221">Fatal</a></h3>
|
|
||||||
<pre>func (c *B) Fatal(args ...interface{})</pre>
|
|
||||||
<p>
|
|
||||||
Fatal is equivalent to Log() followed by FailNow().
|
|
||||||
</p>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h3 id="B.Fatalf">func (*B) <a href="/src/pkg/testing/testing.go?s=8569:8628#L227">Fatalf</a></h3>
|
|
||||||
<pre>func (c *B) Fatalf(format string, args ...interface{})</pre>
|
|
||||||
<p>
|
|
||||||
Fatalf is equivalent to Logf() followed by FailNow().
|
|
||||||
</p>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h3 id="B.Log">func (*B) <a href="/src/pkg/testing/testing.go?s=7763:7804#L202">Log</a></h3>
|
|
||||||
<pre>func (c *B) Log(args ...interface{})</pre>
|
|
||||||
<p>
|
|
||||||
Log formats its arguments using default formatting, analogous to Println(),
|
|
||||||
and records the text in the error log.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h3 id="B.Logf">func (*B) <a href="/src/pkg/testing/testing.go?s=7959:8016#L206">Logf</a></h3>
|
|
||||||
<pre>func (c *B) Logf(format string, args ...interface{})</pre>
|
|
||||||
<p>
|
|
||||||
Logf formats its arguments according to the format, analogous to Printf(),
|
|
||||||
and records the text in the error log.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h3 id="B.ResetTimer">func (*B) <a href="/src/pkg/testing/benchmark.go?s=1503:1527#L48">ResetTimer</a></h3>
|
|
||||||
<pre>func (b *B) ResetTimer()</pre>
|
|
||||||
<p>
|
|
||||||
ResetTimer sets the elapsed benchmark time to zero.
|
|
||||||
It does not affect whether the timer is running.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h3 id="B.SetBytes">func (*B) <a href="/src/pkg/testing/benchmark.go?s=1728:1757#L57">SetBytes</a></h3>
|
|
||||||
<pre>func (b *B) SetBytes(n int64)</pre>
|
|
||||||
<p>
|
|
||||||
SetBytes records the number of bytes processed in a single operation.
|
|
||||||
If this is called, the benchmark will report ns/op and MB/s.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h3 id="B.StartTimer">func (*B) <a href="/src/pkg/testing/benchmark.go?s=1047:1071#L29">StartTimer</a></h3>
|
|
||||||
<pre>func (b *B) StartTimer()</pre>
|
|
||||||
<p>
|
|
||||||
StartTimer starts timing a test. This function is called automatically
|
|
||||||
before a benchmark starts, but it can also used to resume timing after
|
|
||||||
a call to StopTimer.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h3 id="B.StopTimer">func (*B) <a href="/src/pkg/testing/benchmark.go?s=1288:1311#L39">StopTimer</a></h3>
|
|
||||||
<pre>func (b *B) StopTimer()</pre>
|
|
||||||
<p>
|
|
||||||
StopTimer stops timing a test. This can be used to pause the timer
|
|
||||||
while performing complex initialization that you don't
|
|
||||||
want to measure.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h2 id="BenchmarkResult">type <a href="/src/pkg/testing/benchmark.go?s=4206:4391#L165">BenchmarkResult</a></h2>
|
|
||||||
<pre>type BenchmarkResult struct {
|
|
||||||
N int <span class="comment">// The number of iterations.</span>
|
|
||||||
T time.Duration <span class="comment">// The total time taken.</span>
|
|
||||||
Bytes int64 <span class="comment">// Bytes processed in one iteration.</span>
|
|
||||||
}</pre>
|
|
||||||
<p>
|
|
||||||
The results of a benchmark run.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h3 id="Benchmark">func <a href="/src/pkg/testing/benchmark.go?s=7545:7589#L275">Benchmark</a></h3>
|
|
||||||
<pre>func Benchmark(f func(b *B)) BenchmarkResult</pre>
|
|
||||||
<p>
|
|
||||||
Benchmark benchmarks a single function. Useful for creating
|
|
||||||
custom benchmarks that do not use the "go test" command.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h3 id="BenchmarkResult.NsPerOp">func (BenchmarkResult) <a href="/src/pkg/testing/benchmark.go?s=4393:4433#L171">NsPerOp</a></h3>
|
|
||||||
<pre>func (r BenchmarkResult) NsPerOp() int64</pre>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h3 id="BenchmarkResult.String">func (BenchmarkResult) <a href="/src/pkg/testing/benchmark.go?s=4677:4717#L185">String</a></h3>
|
|
||||||
<pre>func (r BenchmarkResult) String() string</pre>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h2 id="InternalBenchmark">type <a href="/src/pkg/testing/benchmark.go?s=555:618#L10">InternalBenchmark</a></h2>
|
|
||||||
<pre>type InternalBenchmark struct {
|
|
||||||
Name string
|
|
||||||
F func(b *B)
|
|
||||||
}</pre>
|
|
||||||
<p>
|
|
||||||
An internal type but exported because it is cross-package; part of the implementation
|
|
||||||
of the "go test" command.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h2 id="InternalExample">type <a href="/src/pkg/testing/example.go?s=236:312#L6">InternalExample</a></h2>
|
|
||||||
<pre>type InternalExample struct {
|
|
||||||
Name string
|
|
||||||
F func()
|
|
||||||
Output string
|
|
||||||
}</pre>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h2 id="InternalTest">type <a href="/src/pkg/testing/testing.go?s=9065:9121#L241">InternalTest</a></h2>
|
|
||||||
<pre>type InternalTest struct {
|
|
||||||
Name string
|
|
||||||
F func(*T)
|
|
||||||
}</pre>
|
|
||||||
<p>
|
|
||||||
An internal type but exported because it is cross-package; part of the implementation
|
|
||||||
of the "go test" command.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h2 id="T">type <a href="/src/pkg/testing/testing.go?s=6070:6199#L156">T</a></h2>
|
|
||||||
<pre>type T struct {
|
|
||||||
<span class="comment">// contains filtered or unexported fields</span>
|
|
||||||
}</pre>
|
|
||||||
<p>
|
|
||||||
T is a type passed to Test functions to manage test state and support formatted test logs.
|
|
||||||
Logs are accumulated during execution and dumped to standard error when done.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h3 id="T.Error">func (*T) <a href="/src/pkg/testing/testing.go?s=8110:8153#L209">Error</a></h3>
|
|
||||||
<pre>func (c *T) Error(args ...interface{})</pre>
|
|
||||||
<p>
|
|
||||||
Error is equivalent to Log() followed by Fail().
|
|
||||||
</p>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h3 id="T.Errorf">func (*T) <a href="/src/pkg/testing/testing.go?s=8253:8312#L215">Errorf</a></h3>
|
|
||||||
<pre>func (c *T) Errorf(format string, args ...interface{})</pre>
|
|
||||||
<p>
|
|
||||||
Errorf is equivalent to Logf() followed by Fail().
|
|
||||||
</p>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h3 id="T.Fail">func (*T) <a href="/src/pkg/testing/testing.go?s=6270:6293#L163">Fail</a></h3>
|
|
||||||
<pre>func (c *T) Fail()</pre>
|
|
||||||
<p>
|
|
||||||
Fail marks the function as having failed but continues execution.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h3 id="T.FailNow">func (*T) <a href="/src/pkg/testing/testing.go?s=6548:6574#L170">FailNow</a></h3>
|
|
||||||
<pre>func (c *T) FailNow()</pre>
|
|
||||||
<p>
|
|
||||||
FailNow marks the function as having failed and stops its execution.
|
|
||||||
Execution will continue at the next test or benchmark.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h3 id="T.Failed">func (*T) <a href="/src/pkg/testing/testing.go?s=6366:6396#L166">Failed</a></h3>
|
|
||||||
<pre>func (c *T) Failed() bool</pre>
|
|
||||||
<p>
|
|
||||||
Failed returns whether the function has failed.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h3 id="T.Fatal">func (*T) <a href="/src/pkg/testing/testing.go?s=8420:8463#L221">Fatal</a></h3>
|
|
||||||
<pre>func (c *T) Fatal(args ...interface{})</pre>
|
|
||||||
<p>
|
|
||||||
Fatal is equivalent to Log() followed by FailNow().
|
|
||||||
</p>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h3 id="T.Fatalf">func (*T) <a href="/src/pkg/testing/testing.go?s=8569:8628#L227">Fatalf</a></h3>
|
|
||||||
<pre>func (c *T) Fatalf(format string, args ...interface{})</pre>
|
|
||||||
<p>
|
|
||||||
Fatalf is equivalent to Logf() followed by FailNow().
|
|
||||||
</p>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h3 id="T.Log">func (*T) <a href="/src/pkg/testing/testing.go?s=7763:7804#L202">Log</a></h3>
|
|
||||||
<pre>func (c *T) Log(args ...interface{})</pre>
|
|
||||||
<p>
|
|
||||||
Log formats its arguments using default formatting, analogous to Println(),
|
|
||||||
and records the text in the error log.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h3 id="T.Logf">func (*T) <a href="/src/pkg/testing/testing.go?s=7959:8016#L206">Logf</a></h3>
|
|
||||||
<pre>func (c *T) Logf(format string, args ...interface{})</pre>
|
|
||||||
<p>
|
|
||||||
Logf formats its arguments according to the format, analogous to Printf(),
|
|
||||||
and records the text in the error log.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h3 id="T.Parallel">func (*T) <a href="/src/pkg/testing/testing.go?s=8809:8831#L234">Parallel</a></h3>
|
|
||||||
<pre>func (t *T) Parallel()</pre>
|
|
||||||
<p>
|
|
||||||
Parallel signals that this test is to be run in parallel with (and only with)
|
|
||||||
other parallel tests in this CPU group.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h2 id="subdirectories">Subdirectories</h2>
|
|
||||||
|
|
||||||
<table class="dir">
|
|
||||||
<tr>
|
|
||||||
<th>Name</th>
|
|
||||||
<th> </th>
|
|
||||||
<th style="text-align: left; width: auto">Synopsis</th>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td><a href="..">..</a></td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td class="name"><a href="iotest">iotest</a></td>
|
|
||||||
<td> </td>
|
|
||||||
<td style="width: auto">Package iotest implements Readers and Writers useful mainly for testing.</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td class="name"><a href="quick">quick</a></td>
|
|
||||||
<td> </td>
|
|
||||||
<td style="width: auto">Package quick implements utility functions to help with black box testing.</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
|
|
||||||
</table>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id="footer">
|
|
||||||
Build version go1.0.2.<br>
|
|
||||||
Except as <a href="http://code.google.com/policies.html#restrictions">noted</a>,
|
|
||||||
the content of this page is licensed under the
|
|
||||||
Creative Commons Attribution 3.0 License,
|
|
||||||
and code is licensed under a <a href="/LICENSE">BSD license</a>.<br>
|
|
||||||
<a href="/doc/tos.html">Terms of Service</a> |
|
|
||||||
<a href="http://www.google.com/intl/en/privacy/privacy-policy.html">Privacy Policy</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<script type="text/javascript">
|
|
||||||
(function() {
|
|
||||||
var ga = document.createElement("script"); ga.type = "text/javascript"; ga.async = true;
|
|
||||||
ga.src = ("https:" == document.location.protocol ? "https://ssl" : "http://www") + ".google-analytics.com/ga.js";
|
|
||||||
var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(ga, s);
|
|
||||||
})();
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
<script type="text/javascript">
|
|
||||||
(function() {
|
|
||||||
var po = document.createElement('script'); po.type = 'text/javascript'; po.async = true;
|
|
||||||
po.src = 'https://apis.google.com/js/plusone.js';
|
|
||||||
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(po, s);
|
|
||||||
})();
|
|
||||||
</script>
|
|
||||||
</html>
|
|
||||||
|
|
1214
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/testdata/gowiki.html
generated
vendored
1214
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/testdata/gowiki.html
generated
vendored
File diff suppressed because it is too large
Load diff
413
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/testdata/metalreview.html
generated
vendored
413
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/testdata/metalreview.html
generated
vendored
|
@ -1,413 +0,0 @@
|
||||||
|
|
||||||
|
|
||||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
|
||||||
|
|
||||||
<html xmlns="http://www.w3.org/1999/xhtml" >
|
|
||||||
<head><meta http-equiv="X-UA-Compatible" content="IE=8" />
|
|
||||||
|
|
||||||
<meta name="keywords" content="metal, reviews, metalreview, metalreviews, heavy, rock, review, music, blogs, forums, community" />
|
|
||||||
<meta name="description" content="Critical heavy metal album and dvd reviews, written by professional writers. Large community with forums, blogs, photos and commenting system." />
|
|
||||||
|
|
||||||
<title>
|
|
||||||
|
|
||||||
|
|
||||||
Metal Reviews, News, Blogs, Interviews and Community | Metal Review
|
|
||||||
|
|
||||||
|
|
||||||
</title><link rel="stylesheet" type="text/css" href="/Content/Css/reset-fonts-grids.css" /><link rel="stylesheet" type="text/css" href="/Content/Css/base.css" /><link rel="stylesheet" type="text/css" href="/Content/Css/core.css" /><link rel="stylesheet" type="text/css" href="/Content/Css/wt-rotator.css" />
|
|
||||||
<script src="/Scripts/jquery-1.4.2.min.js" type="text/javascript"></script>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<script type="text/javascript">
|
|
||||||
var _comscore = _comscore || [];
|
|
||||||
_comscore.push({ c1: "2", c2: "9290245" });
|
|
||||||
(function () {
|
|
||||||
var s = document.createElement("script"), el = document.getElementsByTagName("script")[0]; s.async = true;
|
|
||||||
s.src = (document.location.protocol == "https:" ? "https://sb" : "http://b") + ".scorecardresearch.com/beacon.js";
|
|
||||||
el.parentNode.insertBefore(s, el);
|
|
||||||
})();
|
|
||||||
</script>
|
|
||||||
<noscript>
|
|
||||||
<img src="http://b.scorecardresearch.com/p?c1=2&c2=9290245&cv=2.0&cj=1" />
|
|
||||||
</noscript>
|
|
||||||
|
|
||||||
|
|
||||||
<div id="doc2" class="yui-t7">
|
|
||||||
<div id="hd">
|
|
||||||
|
|
||||||
|
|
||||||
<div id="main-logo"><a href="/" title="Home"><img src="/Content/Images/metal-review-logo.png" alt="Metal Review Home" border="0" /></a></div>
|
|
||||||
<div id="leaderboard-banner">
|
|
||||||
|
|
||||||
<script language="javascript" type="text/javascript"><!--
|
|
||||||
document.write('<scr' + 'ipt language="javascript1.1" src="http://adserver.adtechus.com/addyn/3.0/5110/73085/0/225/ADTECH;loc=100;target=_blank;key=key1+key2+key3+key4;grp=[group];misc=' + new Date().getTime() + '"></scri' + 'pt>');
|
|
||||||
//-->
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<noscript>
|
|
||||||
<a href="http://adserver.adtechus.com/adlink/3.0/5110/73085/0/225/ADTECH;loc=300;key=key1+key2+key3+key4;grp=[group]" target="_blank">
|
|
||||||
<img src="http://adserver.adtechus.com/adserv/3.0/5110/73085/0/225/ADTECH;loc=300;key=key1+key2+key3+key4;grp=[group]" border="0" width="728" height="90" />
|
|
||||||
</a>
|
|
||||||
</noscript>
|
|
||||||
</div>
|
|
||||||
<div id="header-menu-container">
|
|
||||||
<div id="header-menu">
|
|
||||||
<a href="/reviews/browse">REVIEWS</a>
|
|
||||||
<a href="http://community2.metalreview.com/blogs/editorials/default.aspx">FEATURES</a>
|
|
||||||
<a href="/artists/browse">ARTISTS</a>
|
|
||||||
<a href="/reviews/pipeline">PIPELINE</a>
|
|
||||||
<a href="http://community2.metalreview.com/forums">FORUMS</a>
|
|
||||||
<a href="http://community2.metalreview.com/blogs/">BLOGS</a>
|
|
||||||
<a href="/aboutus">ABOUT US</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id="sign-in"><a href="https://metalreview.com/account/signin">SIGN IN</a> | <a href="/account/register">JOIN US</a></div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div id="bd">
|
|
||||||
|
|
||||||
<div id="yui-main">
|
|
||||||
<div class="yui-b">
|
|
||||||
<div class="yui-g">
|
|
||||||
<div class="yui-u first">
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<script src="/Scripts/jquery.wt-rotator.min.js" type="text/javascript"></script>
|
|
||||||
<script src="/Scripts/jquery.wt-rotator-initialize.js" type="text/javascript"></script>
|
|
||||||
<div id="review-showcase-wrapper">
|
|
||||||
<h2 id="showcase-heading">Reviews</h2>
|
|
||||||
<div id="review-showcase">
|
|
||||||
<div class="container">
|
|
||||||
<div class="wt-rotator">
|
|
||||||
<a href="#"></a>
|
|
||||||
<div class="desc">
|
|
||||||
</div>
|
|
||||||
<div class="preloader">
|
|
||||||
</div>
|
|
||||||
<div class="c-panel">
|
|
||||||
<div class="buttons">
|
|
||||||
<div class="prev-btn">
|
|
||||||
</div>
|
|
||||||
<div class="play-btn">
|
|
||||||
</div>
|
|
||||||
<div class="next-btn">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="thumbnails">
|
|
||||||
<ul>
|
|
||||||
|
|
||||||
<li><a href="artist.photo?mrx=4641" title="Serpentine Path - Serpentine Path"></a><a href="/reviews/6844/serpentine-path-serpentine-path"></a>
|
|
||||||
<p style="top: 130px; left: 22px; width: 305px; height:60px;">
|
|
||||||
<img class="rotator-cover-art" src="album.cover?art=6844" alt='Serpentine Path - Serpentine Path' title='Serpentine Path - Serpentine Path' />
|
|
||||||
<span class="title"><strong>Serpentine Path</strong></span><br />
|
|
||||||
Serpentine Path<br />
|
|
||||||
|
|
||||||
</p>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<li><a href="artist.photo?mrx=4635" title="Hunter's Ground - No God But the Wild"></a><a href="/reviews/6830/hunters-ground-no-god-but-the-wild"></a>
|
|
||||||
<p style="top: 130px; left: 22px; width: 305px; height:60px;">
|
|
||||||
<img class="rotator-cover-art" src="album.cover?art=6830" alt='Hunter's Ground - No God But the Wild' title='Hunter's Ground - No God But the Wild' />
|
|
||||||
<span class="title"><strong>Hunter's Ground</strong></span><br />
|
|
||||||
No God But the Wild<br />
|
|
||||||
|
|
||||||
</p>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<li><a href="artist.photo?mrx=1035" title="Blut Aus Nord - 777 - Cosmosophy"></a><a href="/reviews/6829/blut-aus-nord-777---cosmosophy"></a>
|
|
||||||
<p style="top: 130px; left: 22px; width: 305px; height:60px;">
|
|
||||||
<img class="rotator-cover-art" src="album.cover?art=6829" alt='Blut Aus Nord - 777 - Cosmosophy' title='Blut Aus Nord - 777 - Cosmosophy' />
|
|
||||||
<span class="title"><strong>Blut Aus Nord</strong></span><br />
|
|
||||||
777 - Cosmosophy<br />
|
|
||||||
<a href="/tags/10/black"><span class="tag">Black</span></a>
|
|
||||||
</p>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<li><a href="artist.photo?mrx=1217" title="Ufomammut - Oro: Opus Alter"></a><a href="/reviews/6835/ufomammut-oro--opus-alter"></a>
|
|
||||||
<p style="top: 130px; left: 22px; width: 305px; height:60px;">
|
|
||||||
<img class="rotator-cover-art" src="album.cover?art=6835" alt='Ufomammut - Oro: Opus Alter' title='Ufomammut - Oro: Opus Alter' />
|
|
||||||
<span class="title"><strong>Ufomammut</strong></span><br />
|
|
||||||
Oro: Opus Alter<br />
|
|
||||||
<a href="/tags/2/doom"><span class="tag">Doom</span></a>
|
|
||||||
</p>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<li><a href="artist.photo?mrx=4590" title="Resurgency - False Enlightenment"></a><a href="/reviews/6746/resurgency-false-enlightenment"></a>
|
|
||||||
<p style="top: 130px; left: 22px; width: 305px; height:60px;">
|
|
||||||
<img class="rotator-cover-art" src="album.cover?art=6746" alt='Resurgency - False Enlightenment' title='Resurgency - False Enlightenment' />
|
|
||||||
<span class="title"><strong>Resurgency</strong></span><br />
|
|
||||||
False Enlightenment<br />
|
|
||||||
<a href="/tags/1/death"><span class="tag">Death</span></a>
|
|
||||||
</p>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<li><a href="artist.photo?mrx=1360" title="Morgoth - Cursed to Live"></a><a href="/reviews/6800/morgoth-cursed-to-live"></a>
|
|
||||||
<p style="top: 130px; left: 22px; width: 305px; height:60px;">
|
|
||||||
<img class="rotator-cover-art" src="album.cover?art=6800" alt='Morgoth - Cursed to Live' title='Morgoth - Cursed to Live' />
|
|
||||||
<span class="title"><strong>Morgoth</strong></span><br />
|
|
||||||
Cursed to Live<br />
|
|
||||||
<a href="/tags/1/death"><span class="tag">Death</span></a><a href="/tags/31/live"><span class="tag">Live</span></a>
|
|
||||||
</p>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<li><a href="artist.photo?mrx=3879" title="Krallice - Years Past Matter"></a><a href="/reviews/6853/krallice-years-past-matter"></a>
|
|
||||||
<p style="top: 130px; left: 22px; width: 305px; height:60px;">
|
|
||||||
<img class="rotator-cover-art" src="album.cover?art=6853" alt='Krallice - Years Past Matter' title='Krallice - Years Past Matter' />
|
|
||||||
<span class="title"><strong>Krallice</strong></span><br />
|
|
||||||
Years Past Matter<br />
|
|
||||||
<a href="/tags/10/black"><span class="tag">Black</span></a>
|
|
||||||
</p>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<li><a href="artist.photo?mrx=4243" title="Murder Construct - Results"></a><a href="/reviews/6782/murder-construct-results"></a>
|
|
||||||
<p style="top: 130px; left: 22px; width: 305px; height:60px;">
|
|
||||||
<img class="rotator-cover-art" src="album.cover?art=6782" alt='Murder Construct - Results' title='Murder Construct - Results' />
|
|
||||||
<span class="title"><strong>Murder Construct</strong></span><br />
|
|
||||||
Results<br />
|
|
||||||
<a href="/tags/13/grindcore"><span class="tag">Grindcore</span></a>
|
|
||||||
</p>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<li><a href="artist.photo?mrx=251" title="Grave - Endless Procession of Souls"></a><a href="/reviews/6834/grave-endless-procession-of-souls"></a>
|
|
||||||
<p style="top: 130px; left: 22px; width: 305px; height:60px;">
|
|
||||||
<img class="rotator-cover-art" src="album.cover?art=6834" alt='Grave - Endless Procession of Souls' title='Grave - Endless Procession of Souls' />
|
|
||||||
<span class="title"><strong>Grave</strong></span><br />
|
|
||||||
Endless Procession of Souls<br />
|
|
||||||
<a href="/tags/1/death"><span class="tag">Death</span></a>
|
|
||||||
</p>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<li><a href="artist.photo?mrx=3508" title="Master - The New Elite"></a><a href="/reviews/6774/master-the-new-elite"></a>
|
|
||||||
<p style="top: 130px; left: 22px; width: 305px; height:60px;">
|
|
||||||
<img class="rotator-cover-art" src="album.cover?art=6774" alt='Master - The New Elite' title='Master - The New Elite' />
|
|
||||||
<span class="title"><strong>Master</strong></span><br />
|
|
||||||
The New Elite<br />
|
|
||||||
<a href="/tags/1/death"><span class="tag">Death</span></a>
|
|
||||||
</p>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div id="showcase-all-artist-albums">
|
|
||||||
<a href="/reviews/6844/serpentine-path-serpentine-path"><img src="album.cover?art=6844" alt="Serpentine Path - Serpentine Path" /></a><a href="/reviews/6830/hunters-ground-no-god-but-the-wild"><img src="album.cover?art=6830" alt="Hunter's Ground - No God But the Wild" /></a><a href="/reviews/6829/blut-aus-nord-777---cosmosophy"><img src="album.cover?art=6829" alt="Blut Aus Nord - 777 - Cosmosophy" /></a><a href="/reviews/6835/ufomammut-oro--opus-alter"><img src="album.cover?art=6835" alt="Ufomammut - Oro: Opus Alter" /></a><a href="/reviews/6746/resurgency-false-enlightenment"><img src="album.cover?art=6746" alt="Resurgency - False Enlightenment" /></a><a href="/reviews/6800/morgoth-cursed-to-live"><img src="album.cover?art=6800" alt="Morgoth - Cursed to Live" /></a><a href="/reviews/6853/krallice-years-past-matter"><img src="album.cover?art=6853" alt="Krallice - Years Past Matter" /></a><a href="/reviews/6782/murder-construct-results"><img src="album.cover?art=6782" alt="Murder Construct - Results" /></a><a href="/reviews/6834/grave-endless-procession-of-souls"><img src="album.cover?art=6834" alt="Grave - Endless Procession of Souls" /></a><a href="/reviews/6774/master-the-new-elite"><img src="album.cover?art=6774" alt="Master - The New Elite" /></a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="yui-u">
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div id="feature-feed">
|
|
||||||
<h2>Features</h2>
|
|
||||||
<div class="feature-feed-line"><a href="http://community2.metalreview.com/blogs/editorials/archive/2012/08/15/corsair-interview.aspx"><span class="feature-link"><strong>Release The SkyKrakken: Corsair Interview</strong></span></a><br /><span class="publish-date">8/15/2012 by JW</span><img align="left" src="http://community2.metalreview.com/cfs-file.ashx/__key/CommunityServer.Components.Avatars/00.00.00.21.25/4TMR3E1CWERK.jpg" alt="JW's Avatar" width="36px" height="40px" border="0" /></div>
|
|
||||||
<div class="feature-feed-line"><a href="http://community2.metalreview.com/blogs/editorials/archive/2012/08/09/riffology-kreative-evolution-part-iii.aspx"><span class="feature-link"><strong>Riffology: Kreative Evolution, Part III</strong></span></a><br /><span class="publish-date">8/9/2012 by Achilles</span><img align="left" src="http://community2.metalreview.com/cfs-file.ashx/__key/CommunityServer.Components.Avatars/00.00.00.21.44/4THUGH622I68.jpg" alt="Achilles's Avatar" width="40px" height="39px" border="0" /></div>
|
|
||||||
<div class="feature-feed-line"><a href="http://community2.metalreview.com/blogs/editorials/archive/2012/08/02/reverend-s-bazaar-don-t-trend-on-me.aspx"><span class="feature-link"><strong>Reverend's Bazaar - Don't Trend On Me </strong></span></a><br /><span class="publish-date">8/2/2012 by Reverend Campbell</span><img align="left" src="http://community2.metalreview.com/cfs-file.ashx/__key/CommunityServer.Components.Avatars/00.00.00.21.18/4TM06FD0ND4G.png" alt="Reverend Campbell's Avatar" width="34px" height="40px" border="0" /></div>
|
|
||||||
<div class="feature-feed-line"><a href="http://community2.metalreview.com/blogs/editorials/archive/2012/08/01/grand-theft-metal-three-for-free.aspx"><span class="feature-link"><strong>Grand Theft Metal - Free Four All </strong></span></a><br /><span class="publish-date">8/2/2012 by Dave</span><img align="left" src="http://community2.metalreview.com/cfs-file.ashx/__key/CommunityServer.Components.Avatars/00.00.00.22.16/4TKJCJQ00VFO.jpg" alt="Dave's Avatar" width="33px" height="40px" border="0" /></div>
|
|
||||||
<div class="feature-feed-line"><a href="http://community2.metalreview.com/blogs/editorials/archive/2012/07/29/monday-with-moonspell-the-interview.aspx"><span class="feature-link"><strong>A Monday with Moonspell: The Interview</strong></span></a><br /><span class="publish-date">7/29/2012 by raetamacue</span><img align="left" src="http://community2.metalreview.com/cfs-file.ashx/__key/CommunityServer.Components.Avatars/00.00.00.71.26/4TLIHKLUSXF4.jpg" alt="raetamacue's Avatar" width="37px" height="40px" border="0" /></div>
|
|
||||||
<div class="feature-feed-line"><a href="http://community2.metalreview.com/blogs/editorials/archive/2012/07/26/riffology-kreative-evolution-part-ii.aspx"><span class="feature-link"><strong>Riffology: Kreative Evolution Part II</strong></span></a><br /><span class="publish-date">7/26/2012 by Achilles</span><img align="left" src="http://community2.metalreview.com/cfs-file.ashx/__key/CommunityServer.Components.Avatars/00.00.00.21.44/4THUGH622I68.jpg" alt="Achilles's Avatar" width="40px" height="39px" border="0" /></div>
|
|
||||||
<div class="feature-feed-line"><a href="http://community2.metalreview.com/blogs/editorials/archive/2012/07/24/shadow-kingdom-records-giveaway.aspx"><span class="feature-link"><strong>WINNERS ANNOUNCED -- Shadow Kingdom Records Give...</strong></span></a><br /><span class="publish-date">7/24/2012 by Metal Review</span><img align="left" src="http://community2.metalreview.com/cfs-file.ashx/__key/CommunityServer.Components.Avatars/00.00.00.59.06/4TFD2N58B7BS.png" alt="Metal Review's Avatar" width="34px" height="40px" border="0" /></div>
|
|
||||||
|
|
||||||
<br />
|
|
||||||
<a href="http://community2.metalreview.com/blogs/editorials/default.aspx"><strong>More Editorials</strong></a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="yui-b">
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<script src="/Scripts/jquery.cycle.all.min.js" type="text/javascript"></script>
|
|
||||||
<div id="slider-next-button"><img id="slider-next" src="/Content/Images/Backgrounds/rotator-next-button.png" alt="Goto Next Group" title="Goto Next Group" /></div>
|
|
||||||
<div id="slider-back-button"><img id="slider-back" src="/Content/Images/Backgrounds/rotator-back-button.png" alt="Goto Previous Group" title="Goto Previous Group" /></div>
|
|
||||||
<div id="latest-reviews-slider">
|
|
||||||
<div class="slider-row">
|
|
||||||
<div class="slider-item"><a href="/reviews/6795/midnight-complete-and-total-hell"><img src="album.cover?art=6795" alt="Midnight Complete and Total Hell" /><br /><strong>Midnight</strong><br /><em>Complete and Total Hell</em></a><div class="score">8.5</div></div>
|
|
||||||
<div class="slider-item"><a href="/reviews/6842/over-your-threshold-facticity"><img src="album.cover?art=6842" alt="Over Your Threshold Facticity" /><br /><strong>Over Your Threshold</strong><br /><em>Facticity</em></a><div class="score">6.0</div></div>
|
|
||||||
<div class="slider-item"><a href="/reviews/6813/nuclear-death-terror-chaos-reigns"><img src="album.cover?art=6813" alt="Nuclear Death Terror Chaos Reigns" /><br /><strong>Nuclear Death Terror</strong><br /><em>Chaos Reigns</em></a><div class="score">7.5</div></div>
|
|
||||||
<div class="slider-item"><a href="/reviews/6811/evoken-atra-mors"><img src="album.cover?art=6811" alt="Evoken Atra Mors" /><br /><strong>Evoken</strong><br /><em>Atra Mors</em></a><div class="score">9.5</div></div>
|
|
||||||
<div class="slider-item"><a href="/reviews/6807/blacklodge-machination"><img src="album.cover?art=6807" alt="Blacklodge MachinatioN" /><br /><strong>Blacklodge</strong><br /><em>MachinatioN</em></a><div class="score">5.5</div></div>
|
|
||||||
<div class="slider-item"><a href="/reviews/6832/prototype-catalyst"><img src="album.cover?art=6832" alt="Prototype Catalyst" /><br /><strong>Prototype</strong><br /><em>Catalyst</em></a><div class="score">8.0</div></div>
|
|
||||||
<div class="slider-item"><a href="/reviews/6822/hypnosia-horror-infernal"><img src="album.cover?art=6822" alt="Hypnosia Horror Infernal" /><br /><strong>Hypnosia</strong><br /><em>Horror Infernal</em></a><div class="score">7.0</div></div>
|
|
||||||
<div class="slider-item"><a href="/reviews/6787/om-advaitic-songs"><img src="album.cover?art=6787" alt="OM Advaitic Songs" /><br /><strong>OM</strong><br /><em>Advaitic Songs</em></a><div class="score">8.0</div></div>
|
|
||||||
<div class="slider-item"><a href="/reviews/6765/afgrund-the-age-of-dumb"><img src="album.cover?art=6765" alt="Afgrund The Age Of Dumb" /><br /><strong>Afgrund</strong><br /><em>The Age Of Dumb</em></a><div class="score">8.5</div></div>
|
|
||||||
<div class="slider-item"><a href="/reviews/6773/binah-hallucinating-in-resurrecture"><img src="album.cover?art=6773" alt="Binah Hallucinating in Resurrecture" /><br /><strong>Binah</strong><br /><em>Hallucinating in Resurrecture</em></a><div class="score">8.5</div></div>
|
|
||||||
</div>
|
|
||||||
<div class="slider-row">
|
|
||||||
<div class="slider-item"><a href="/reviews/6802/deiphago-satan-alpha-omega"><img src="album.cover?art=6802" alt="Deiphago Satan Alpha Omega" /><br /><strong>Deiphago</strong><br /><em>Satan Alpha Omega</em></a><div class="score">8.0</div></div>
|
|
||||||
<div class="slider-item"><a href="/reviews/6719/conan-monnos"><img src="album.cover?art=6719" alt="Conan Monnos" /><br /><strong>Conan</strong><br /><em>Monnos</em></a><div class="score">8.0</div></div>
|
|
||||||
<div class="slider-item"><a href="/reviews/6702/alaric-alaric-atriarch---split-lp"><img src="album.cover?art=6702" alt="Alaric Alaric/Atriarch - Split LP" /><br /><strong>Alaric</strong><br /><em>Alaric/Atriarch - Split LP</em></a><div class="score">8.5</div></div>
|
|
||||||
<div class="slider-item"><a href="/reviews/6780/coven-worship-new-gods-(reissue)"><img src="album.cover?art=6780" alt="Coven Worship New Gods (Reissue)" /><br /><strong>Coven</strong><br /><em>Worship New Gods (Reissue)</em></a><div class="score">5.0</div></div>
|
|
||||||
<div class="slider-item"><a href="/reviews/6831/the-foreshadowing-second-world"><img src="album.cover?art=6831" alt="The Foreshadowing Second World" /><br /><strong>The Foreshadowing</strong><br /><em>Second World</em></a><div class="score">5.5</div></div>
|
|
||||||
<div class="slider-item"><a href="/reviews/6815/nether-regions-into-the-breach"><img src="album.cover?art=6815" alt="Nether Regions Into The Breach" /><br /><strong>Nether Regions</strong><br /><em>Into The Breach</em></a><div class="score">7.0</div></div>
|
|
||||||
<div class="slider-item"><a href="/reviews/6824/agalloch-faustian-echoes"><img src="album.cover?art=6824" alt="Agalloch Faustian Echoes" /><br /><strong>Agalloch</strong><br /><em>Faustian Echoes</em></a><div class="score">9.0</div></div>
|
|
||||||
<div class="slider-item"><a href="/reviews/6805/a-forest-of-stars-a-shadowplay-for-yesterdays"><img src="album.cover?art=6805" alt="A Forest Of Stars A Shadowplay For Yesterdays" /><br /><strong>A Forest Of Stars</strong><br /><em>A Shadowplay For Yesterdays</em></a><div class="score">9.0</div></div>
|
|
||||||
<div class="slider-item"><a href="/reviews/6763/de-profundis-the-emptiness-within"><img src="album.cover?art=6763" alt="De Profundis The Emptiness Within" /><br /><strong>De Profundis</strong><br /><em>The Emptiness Within</em></a><div class="score">7.5</div></div>
|
|
||||||
<div class="slider-item"><a href="/reviews/6826/ozzy-osbourne-speak-of-the-devil"><img src="album.cover?art=6826" alt="Ozzy Osbourne Speak of the Devil" /><br /><strong>Ozzy Osbourne</strong><br /><em>Speak of the Devil</em></a><div class="score">7.5</div></div>
|
|
||||||
</div>
|
|
||||||
<div class="slider-row">
|
|
||||||
<div class="slider-item"><a href="/reviews/6825/testament-dark-roots-of-earth"><img src="album.cover?art=6825" alt="Testament Dark Roots of Earth" /><br /><strong>Testament</strong><br /><em>Dark Roots of Earth</em></a><div class="score">8.0</div></div>
|
|
||||||
<div class="slider-item"><a href="/reviews/6796/eagle-twin-the-feather-tipped-the-serpents-scale"><img src="album.cover?art=6796" alt="Eagle Twin The Feather Tipped The Serpent's Scale" /><br /><strong>Eagle Twin</strong><br /><em>The Feather Tipped The Serpent's Scale</em></a><div class="score">8.5</div></div>
|
|
||||||
<div class="slider-item"><a href="/reviews/6609/king-forged-by-satans-doctrine"><img src="album.cover?art=6609" alt="King Forged by Satan's Doctrine" /><br /><strong>King</strong><br /><em>Forged by Satan's Doctrine</em></a><div class="score">5.5</div></div>
|
|
||||||
<div class="slider-item"><a href="/reviews/6798/khors-wisdom-of-centuries"><img src="album.cover?art=6798" alt="Khors Wisdom of Centuries" /><br /><strong>Khors</strong><br /><em>Wisdom of Centuries</em></a><div class="score">8.5</div></div>
|
|
||||||
<div class="slider-item"><a href="/reviews/6776/samothrace-reverence-to-stone"><img src="album.cover?art=6776" alt="Samothrace Reverence To Stone" /><br /><strong>Samothrace</strong><br /><em>Reverence To Stone</em></a><div class="score">8.0</div></div>
|
|
||||||
<div class="slider-item"><a href="/reviews/6784/horseback-on-the-eclipse"><img src="album.cover?art=6784" alt="Horseback On the Eclipse" /><br /><strong>Horseback</strong><br /><em>On the Eclipse</em></a><div class="score">8.0</div></div>
|
|
||||||
<div class="slider-item"><a href="/reviews/6690/incoming-cerebral-overdrive-le-stelle--a-voyage-adrift"><img src="album.cover?art=6690" alt="Incoming Cerebral Overdrive Le Stelle: A Voyage Adrift" /><br /><strong>Incoming Cerebral Overdrive</strong><br /><em>Le Stelle: A Voyage Adrift</em></a><div class="score">7.5</div></div>
|
|
||||||
<div class="slider-item"><a href="/reviews/6658/struck-by-lightning-true-predation"><img src="album.cover?art=6658" alt="Struck By Lightning True Predation" /><br /><strong>Struck By Lightning</strong><br /><em>True Predation</em></a><div class="score">7.0</div></div>
|
|
||||||
<div class="slider-item"><a href="/reviews/6772/offending-age-of-perversion"><img src="album.cover?art=6772" alt="Offending Age of Perversion" /><br /><strong>Offending</strong><br /><em>Age of Perversion</em></a><div class="score">7.5</div></div>
|
|
||||||
<div class="slider-item"><a href="/reviews/6804/king-of-asgard----to-north"><img src="album.cover?art=6804" alt="King Of Asgard ...to North" /><br /><strong>King Of Asgard</strong><br /><em>...to North</em></a><div class="score">7.5</div></div>
|
|
||||||
</div>
|
|
||||||
<div class="slider-row">
|
|
||||||
<div class="slider-item"><a href="/reviews/6783/burning-love-rotten-thing-to-say"><img src="album.cover?art=6783" alt="Burning Love Rotten Thing to Say" /><br /><strong>Burning Love</strong><br /><em>Rotten Thing to Say</em></a><div class="score">7.0</div></div>
|
|
||||||
<div class="slider-item"><a href="/reviews/6770/high-on-fire-the-art-of-self-defense-(reissue)"><img src="album.cover?art=6770" alt="High On Fire The Art Of Self Defense (Reissue)" /><br /><strong>High On Fire</strong><br /><em>The Art Of Self Defense (Reissue)</em></a><div class="score">7.5</div></div>
|
|
||||||
<div class="slider-item"><a href="/reviews/6660/horseback-half-blood"><img src="album.cover?art=6660" alt="Horseback Half Blood" /><br /><strong>Horseback</strong><br /><em>Half Blood</em></a><div class="score">6.5</div></div>
|
|
||||||
<div class="slider-item"><a href="/reviews/6732/aldebaran-embracing-the-lightless-depths"><img src="album.cover?art=6732" alt="Aldebaran Embracing the Lightless Depths" /><br /><strong>Aldebaran</strong><br /><em>Embracing the Lightless Depths</em></a><div class="score">8.0</div></div>
|
|
||||||
<div class="slider-item"><a href="/reviews/6778/tank-war-nation"><img src="album.cover?art=6778" alt="Tank War Nation" /><br /><strong>Tank</strong><br /><em>War Nation</em></a><div class="score">6.5</div></div>
|
|
||||||
<div class="slider-item"><a href="/reviews/6793/satanic-bloodspraying-at-the-mercy-of-satan"><img src="album.cover?art=6793" alt="Satanic Bloodspraying At the Mercy of Satan" /><br /><strong>Satanic Bloodspraying</strong><br /><em>At the Mercy of Satan</em></a><div class="score">8.5</div></div>
|
|
||||||
<div class="slider-item"><a href="/reviews/6791/from-ashes-rise-rejoice-the-end---rage-of-sanity"><img src="album.cover?art=6791" alt="From Ashes Rise Rejoice The End / Rage Of Sanity" /><br /><strong>From Ashes Rise</strong><br /><em>Rejoice The End / Rage Of Sanity</em></a><div class="score">8.0</div></div>
|
|
||||||
<div class="slider-item"><a href="/reviews/6743/ereb-altor-gastrike"><img src="album.cover?art=6743" alt="Ereb Altor Gastrike" /><br /><strong>Ereb Altor</strong><br /><em>Gastrike</em></a><div class="score">8.0</div></div>
|
|
||||||
<div class="slider-item"><a href="/reviews/6794/catheter-southwest-doom-violence"><img src="album.cover?art=6794" alt="Catheter Southwest Doom Violence" /><br /><strong>Catheter</strong><br /><em>Southwest Doom Violence</em></a><div class="score">7.0</div></div>
|
|
||||||
<div class="slider-item"><a href="/reviews/6759/power-theory-an-axe-to-grind"><img src="album.cover?art=6759" alt="Power Theory An Axe to Grind" /><br /><strong>Power Theory</strong><br /><em>An Axe to Grind</em></a><div class="score">6.0</div></div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<script type="text/javascript">
|
|
||||||
$(document).ready(function () {
|
|
||||||
$('#latest-reviews-slider').cycle({
|
|
||||||
fx: 'scrollRight',
|
|
||||||
speed: 'fast',
|
|
||||||
timeout: 0,
|
|
||||||
next: '#slider-next-button',
|
|
||||||
prev: '#slider-back-button'
|
|
||||||
});
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<div id="homepage-mid-horizontal-zone">
|
|
||||||
<script language="javascript" type="text/javascript" src="http://metalreview.com/bannermgr/abm.aspx?z=1"></script>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div id="news-feed">
|
|
||||||
<h2>News</h2><div class="news-feed-line"><a href="http://www.bravewords.com/news/190057" target="_blank"><span class="news-link"><strong><span class="new-news">NEW</span> CENTURIAN To Release Contra Rationem Album This Winter</strong></span></a><br /><span class="publish-date">9/12/2012</span></div><br />
|
|
||||||
<div class="news-feed-line"><a href="http://www.bravewords.com/news/190056" target="_blank"><span class="news-link"><strong><span class="new-news">NEW</span> Southwest Terror Fest 2012 - Lineup Changes Announced</strong></span></a><br /><span class="publish-date">9/12/2012</span></div><br />
|
|
||||||
<div class="news-feed-line"><a href="http://www.bravewords.com/news/190055" target="_blank"><span class="news-link"><strong><span class="new-news">NEW</span> ROB ZOMBIE Premiers The Lords Of Salem At TIFF; Q&A Video Posted</strong></span></a><br /><span class="publish-date">9/12/2012</span></div><br />
|
|
||||||
<div class="news-feed-line"><a href="http://www.bravewords.com/news/190054" target="_blank"><span class="news-link"><strong><span class="new-news">NEW</span> THIN LIZZY Keyboardist Darren Wharton's DARE - Calm Before The Storm 2 Album Details Revealed</strong></span></a><br /><span class="publish-date">9/12/2012</span></div><br />
|
|
||||||
<div class="news-feed-line"><a href="http://www.bravewords.com/news/190053" target="_blank"><span class="news-link"><strong><span class="new-news">NEW</span> Japan's LIV MOON To Release Fourth Album; Features Past/Present Members Of EUROPE, ANGRA, HAMMERFALL</strong></span></a><br /><span class="publish-date">9/12/2012</span></div><br />
|
|
||||||
<div class="news-feed-line"><a href="http://www.bravewords.com/news/190052" target="_blank"><span class="news-link"><strong><span class="new-news">NEW</span> SLASH - Sydney Show To Premier This Friday, Free And In HD; Trailer Posted</strong></span></a><br /><span class="publish-date">9/12/2012</span></div><br />
|
|
||||||
<div class="news-feed-line"><a href="http://www.bravewords.com/news/190051" target="_blank"><span class="news-link"><strong><span class="new-news">NEW</span> KHAØS - New Band Featuring Members Of OUTLOUD, TRIBAL, JORN And ELIS To Release New EP In October; Teaser Posted </strong></span></a><br /><span class="publish-date">9/12/2012</span></div><br />
|
|
||||||
<div class="news-feed-line"><a href="http://www.bravewords.com/news/190050" target="_blank"><span class="news-link"><strong><span class="new-news">NEW</span> RECKLESS LOVE Confirm Guests For London Residency Shows In October</strong></span></a><br /><span class="publish-date">9/12/2012</span></div><br />
|
|
||||||
<div class="news-feed-line"><a href="http://www.bravewords.com/news/190049" target="_blank"><span class="news-link"><strong>NASHVILLE PUSSY Add Dates In France, Sweden To European Tour Schedule; Bassist Karen Cuda Sidelined With Back Injury </strong></span></a><br /><span class="publish-date">9/12/2012</span></div><br />
|
|
||||||
<div class="news-feed-line"><a href="http://www.bravewords.com/news/190048" target="_blank"><span class="news-link"><strong>CALIBAN Post Behind-The-Scenes Tour Footage</strong></span></a><br /><span class="publish-date">9/12/2012</span></div><br />
|
|
||||||
<div class="news-feed-line"><a href="http://www.bravewords.com/news/190047" target="_blank"><span class="news-link"><strong>Ex-MERCYFUL FATE Drummer Kim Ruzz Forms New Band METALRUZZ</strong></span></a><br /><span class="publish-date">9/12/2012</span></div><br />
|
|
||||||
<div class="news-feed-line"><a href="http://www.bravewords.com/news/190046" target="_blank"><span class="news-link"><strong>GRAVE Mainman On Endless Procession Of Souls - "These Are The Most ‘Song-Oriented’ Tracks We’ve Done In A Long Time"</strong></span></a><br /><span class="publish-date">9/12/2012</span></div><br />
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div id="lashes-feed">
|
|
||||||
<h2>Lashes</h2>
|
|
||||||
<div class="lashes-feed-line"><a href="/reviews/6855/katatonia-dead-end-kings#81760"><span class="new-lash">NEW</span> <span class="lashes-link"><strong>Katatonia - Dead End Kings</strong></span></a><br /><span class="publish-date">45 minutes ago by Chaosjunkie</span></div>
|
|
||||||
<div class="lashes-feed-line"><a href="/reviews/6855/katatonia-dead-end-kings#81759"><span class="lashes-link"><strong>Katatonia - Dead End Kings</strong></span></a><br /><span class="publish-date">1 hour ago by Harry Dick Rotten</span></div>
|
|
||||||
<div class="lashes-feed-line"><a href="/reviews/6746/resurgency-false-enlightenment#81758"><span class="lashes-link"><strong>Resurgency - False Enlightenment</strong></span></a><br /><span class="publish-date">3 hours ago by Anonymous</span></div>
|
|
||||||
<div class="lashes-feed-line"><a href="/reviews/4095/witchcraft-the-alchemist#81757"><span class="lashes-link"><strong>Witchcraft - The Alchemist</strong></span></a><br /><span class="publish-date">5 hours ago by Luke_22</span></div>
|
|
||||||
<div class="lashes-feed-line"><a href="/reviews/6855/katatonia-dead-end-kings#81756"><span class="lashes-link"><strong>Katatonia - Dead End Kings</strong></span></a><br /><span class="publish-date">9 hours ago by chaosjunkie</span></div>
|
|
||||||
<div class="lashes-feed-line"><a href="/reviews/6855/katatonia-dead-end-kings#81755"><span class="lashes-link"><strong>Katatonia - Dead End Kings</strong></span></a><br /><span class="publish-date">10 hours ago by Compeller</span></div>
|
|
||||||
<div class="lashes-feed-line"><a href="/reviews/6827/manetheren-time#81754"><span class="lashes-link"><strong>Manetheren - Time</strong></span></a><br /><span class="publish-date">10 hours ago by xpmule</span></div>
|
|
||||||
<div class="lashes-feed-line"><a href="/reviews/6835/ufomammut-oro--opus-alter#81753"><span class="lashes-link"><strong>Ufomammut - Oro: Opus Alter</strong></span></a><br /><span class="publish-date">16 hours ago by Anonymous</span></div>
|
|
||||||
<div class="lashes-feed-line"><a href="/reviews/6835/ufomammut-oro--opus-alter#81752"><span class="lashes-link"><strong>Ufomammut - Oro: Opus Alter</strong></span></a><br /><span class="publish-date">17 hours ago by Harry Dick Rotten</span></div>
|
|
||||||
<div class="lashes-feed-line"><a href="/reviews/6855/katatonia-dead-end-kings#81751"><span class="lashes-link"><strong>Katatonia - Dead End Kings</strong></span></a><br /><span class="publish-date">yesterday by Chaosjunkie</span></div>
|
|
||||||
<div class="lashes-feed-line"><a href="/reviews/6855/katatonia-dead-end-kings#81750"><span class="lashes-link"><strong>Katatonia - Dead End Kings</strong></span></a><br /><span class="publish-date">yesterday by Anonymous</span></div>
|
|
||||||
<div class="lashes-feed-line"><a href="/reviews/6855/katatonia-dead-end-kings#81749"><span class="lashes-link"><strong>Katatonia - Dead End Kings</strong></span></a><br /><span class="publish-date">yesterday by Anonymous</span></div>
|
|
||||||
<div class="lashes-feed-line"><a href="/reviews/6855/katatonia-dead-end-kings#81748"><span class="lashes-link"><strong>Katatonia - Dead End Kings</strong></span></a><br /><span class="publish-date">yesterday by Anonymous</span></div>
|
|
||||||
<div class="lashes-feed-line"><a href="/reviews/6855/katatonia-dead-end-kings#81747"><span class="lashes-link"><strong>Katatonia - Dead End Kings</strong></span></a><br /><span class="publish-date">yesterday by frantic</span></div>
|
|
||||||
<div class="lashes-feed-line"><a href="/reviews/6829/blut-aus-nord-777---cosmosophy#81746"><span class="lashes-link"><strong>Blut Aus Nord - 777 - Cosmosophy</strong></span></a><br /><span class="publish-date">yesterday by Dimensional Bleedthrough</span></div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div id="ft">
|
|
||||||
|
|
||||||
|
|
||||||
<div id="template-footer">
|
|
||||||
<div class="left-column">
|
|
||||||
<ul>
|
|
||||||
<li><a href="/">Home</a></li>
|
|
||||||
<li><a href="/reviews/browse">Reviews</a></li>
|
|
||||||
<li><a href="/tags">Genre Tags</a></li>
|
|
||||||
<li><a href="http://community2.metalreview.com/blogs/editorials/default.aspx">Features</a></li>
|
|
||||||
<li><a href="/artists/browse">Artists</a></li>
|
|
||||||
<li><a href="/reviews/pipeline">Pipeline</a></li>
|
|
||||||
<li><a href="http://community2.metalreview.com/forums">Forums</a></li>
|
|
||||||
<li><a href="/aboutus">About Us</a></li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<div class="middle-column">
|
|
||||||
<ul>
|
|
||||||
<li><a href="/aboutus/disclaimer">Disclaimer</a></li>
|
|
||||||
<li><a href="/aboutus/privacypolicy">Privacy Policy</a></li>
|
|
||||||
<li><a href="/aboutus/advertising">Advertising</a></li>
|
|
||||||
<li><a href="http://community2.metalreview.com/blogs/eminor/archive/2008/10/27/write-for-metal-review.aspx">Write For Us</a></li>
|
|
||||||
<li><a href="/contactus">Contact Us</a></li>
|
|
||||||
<li><a href="/contactus">Digital Promos</a></li>
|
|
||||||
<li><a href="/contactus">Mailing Address</a></li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<div class="right-column">
|
|
||||||
<ul>
|
|
||||||
<li><a href="http://feeds.feedburner.com/metalreviews">Reviews RSS Feed</a></li>
|
|
||||||
<li><a href="http://twitter.com/metalreview">Twitter</a></li>
|
|
||||||
<li><a href="http://www.myspace.com/metalreviewdotcom">MySpace</a></li>
|
|
||||||
<li><a href="http://www.last.fm/group/MetalReview.com">Last.fm</a></li>
|
|
||||||
<li><a href="http://www.facebook.com/pages/MetalReviewcom/48371319443">Facebook</a></li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<div class="square-ad">
|
|
||||||
|
|
||||||
|
|
||||||
<!--JavaScript Tag // Tag for network 5110: Fixion Media // Website: Metalreview // Page: ROS // Placement: ROS-Middle-300 x 250 (1127996) // created at: Oct 19, 2009 6:48:27 PM-->
|
|
||||||
<script type="text/javascript" language="javascript"><!--
|
|
||||||
document.write('<scr' + 'ipt language="javascript1.1" src="http://adserver.adtechus.com/addyn/3.0/5110/1127996/0/170/ADTECH;loc=100;target=_blank;key=key1+key2+key3+key4;grp=[group];misc=' + new Date().getTime() + '"></scri' + 'pt>');
|
|
||||||
//-->
|
|
||||||
</script><noscript><a href="http://adserver.adtechus.com/adlink/3.0/5110/1127996/0/170/ADTECH;loc=300;key=key1+key2+key3+key4;grp=[group]" target="_blank"><img src="http://adserver.adtechus.com/adserv/3.0/5110/1127996/0/170/ADTECH;loc=300;key=key1+key2+key3+key4;grp=[group]" border="0" width="300" height="250"></a></noscript>
|
|
||||||
<!-- End of JavaScript Tag -->
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<script type="text/javascript">
|
|
||||||
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
|
|
||||||
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<script type="text/javascript">
|
|
||||||
var pageTracker = _gat._getTracker("UA-3455310-1");
|
|
||||||
pageTracker._initData();
|
|
||||||
pageTracker._trackPageview();
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<!--JavaScript Tag // Tag for network 5110: Fixion Media // Website: Metalreview // Page: BACKGROUND ADS // Placement: BACKGROUND ADS-Top-1 x 1 (2186116) // created at: Aug 18, 2011 7:20:38 PM-->
|
|
||||||
<script language="javascript"><!--
|
|
||||||
document.write('<scr' + 'ipt language="javascript1.1" src="http://adserver.adtechus.com/addyn/3.0/5110/2186116/0/16/ADTECH;loc=100;target=_blank;key=key1+key2+key3+key4;grp=[group];misc=' + new Date().getTime() + '"></scri' + 'pt>');
|
|
||||||
//-->
|
|
||||||
</script><noscript><a href="http://adserver.adtechus.com/adlink/3.0/5110/2186116/0/16/ADTECH;loc=300;key=key1+key2+key3+key4;grp=[group]" target="_blank"><img src="http://adserver.adtechus.com/adserv/3.0/5110/2186116/0/16/ADTECH;loc=300;key=key1+key2+key3+key4;grp=[group]" border="0" width="1" height="1"></a></noscript>
|
|
||||||
<!-- End of JavaScript Tag -->
|
|
||||||
|
|
||||||
</body>
|
|
||||||
</html>
|
|
102
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/testdata/page.html
generated
vendored
102
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/testdata/page.html
generated
vendored
|
@ -1,102 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en" ng-app="app">
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
|
||||||
<title>
|
|
||||||
Provok.in
|
|
||||||
</title>
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
||||||
<meta name="description" content="Provok.in - Prove your point. State an affirmation, back it up with evidence, unveil the truth.">
|
|
||||||
<meta name="author" content="Martin Angers">
|
|
||||||
<link href="http://fonts.googleapis.com/css?family=Belgrano" rel="stylesheet" type="text/css">
|
|
||||||
<!--[if lt IE 9]><link href="http://fonts.googleapis.com/css?family=Belgrano" rel="stylesheet" type="text/css"><link href="http://fonts.googleapis.com/css?family=Belgrano:400italic" rel="stylesheet" type="text/css"><link href="http://fonts.googleapis.com/css?family=Belgrano:700" rel="stylesheet" type="text/css"><link href="http://fonts.googleapis.com/css?family=Belgrano:700italic" rel="stylesheet" type="text/css"><![endif]-->
|
|
||||||
<link href="/css/pvk.min.css" rel="stylesheet" type="text/css">
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div class="container-fluid" id="cf1">
|
|
||||||
<div class="row-fluid">
|
|
||||||
<div class="pvk-gutter">
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<div class="pvk-content" id="pc1">
|
|
||||||
<div ng-controller="HeroCtrl" class="hero-unit">
|
|
||||||
<div class="container-fluid" id="cf2">
|
|
||||||
<div class="row-fluid" id="cf2-1">
|
|
||||||
<div class="span12">
|
|
||||||
<h1>
|
|
||||||
<a href="/">Provok<span class="green">.</span><span class="red">i</span>n</a>
|
|
||||||
</h1>
|
|
||||||
<p>
|
|
||||||
Prove your point.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row-fluid" id="cf2-2">
|
|
||||||
<div class="span12 alert alert-error">
|
|
||||||
<strong>Beta Version.</strong> Things may change. Or disappear. Or fail miserably. If it's the latter, <a href="https://github.com/PuerkitoBio/Provok.in-issues" target="_blank" class="link">please file an issue.</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div ng-cloak="" ng-show="isLoggedOut() && !hideLogin" class="row-fluid" id="cf2-3">
|
|
||||||
<a ng-href="{{ROUTES.login}}" class="btn btn-primary">Sign in. Painless.</a> <span>or</span> <a ng-href="{{ROUTES.help}}" class="link">learn more about provok.in.</a>
|
|
||||||
</div>
|
|
||||||
<div ng-cloak="" ng-show="isLoggedIn()" class="row-fluid logged-in-state" id="cf2-4">
|
|
||||||
<span>Welcome,</span> <a ng-href="{{ROUTES.profile}}" class="link">{{getUserName()}}</a> <span>(</span> <a ng-click="doLogout($event)" class="link">logout</a> <span>)</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="pvk-gutter">
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row-fluid">
|
|
||||||
<div class="pvk-gutter">
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<div class="pvk-content" id="pc2">
|
|
||||||
<div class="container-fluid" id="cf3">
|
|
||||||
<div class="row-fluid">
|
|
||||||
<div ng-cloak="" view-on-display="" ng-controller="MsgCtrl" ng-class="{'displayed': blockIsDisplayed}" class="message-box">
|
|
||||||
<div ng-class="{'alert-info': isInfo, 'alert-error': !isInfo, 'displayed': isDisplayed}" class="alert">
|
|
||||||
<a ng-click="hideMessage(true, $event)" class="close">×</a>
|
|
||||||
<h4 class="alert-heading">
|
|
||||||
{{ title }}
|
|
||||||
</h4>
|
|
||||||
<p>
|
|
||||||
{{ message }}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="container-fluid" id="cf4">
|
|
||||||
<div ng-controller="ShareCtrl" ng-hide="isHidden" class="row-fluid center-content"></div>
|
|
||||||
</div>
|
|
||||||
<div ng-view=""></div>
|
|
||||||
</div>
|
|
||||||
<div class="pvk-gutter">
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row-fluid">
|
|
||||||
<div class="pvk-gutter">
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<div class="pvk-content">
|
|
||||||
<div class="footer">
|
|
||||||
<p>
|
|
||||||
<a href="/" class="link">Home</a> <span>|</span> <a href="/about" class="link">About</a> <span>|</span> <a href="/help" class="link">Help</a>
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<small>© 2012 Martin Angers</small>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="pvk-gutter">
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
24
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/testdata/page2.html
generated
vendored
24
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/testdata/page2.html
generated
vendored
|
@ -1,24 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>Tests for siblings</title>
|
|
||||||
</head>
|
|
||||||
<BODY>
|
|
||||||
<div id="main">
|
|
||||||
<div id="n1" class="one even row"></div>
|
|
||||||
<div id="n2" class="two odd row"></div>
|
|
||||||
<div id="n3" class="three even row"></div>
|
|
||||||
<div id="n4" class="four odd row"></div>
|
|
||||||
<div id="n5" class="five even row"></div>
|
|
||||||
<div id="n6" class="six odd row"></div>
|
|
||||||
</div>
|
|
||||||
<div id="foot">
|
|
||||||
<div id="nf1" class="one even row"></div>
|
|
||||||
<div id="nf2" class="two odd row"></div>
|
|
||||||
<div id="nf3" class="three even row"></div>
|
|
||||||
<div id="nf4" class="four odd row"></div>
|
|
||||||
<div id="nf5" class="five even row odder"></div>
|
|
||||||
<div id="nf6" class="six odd row"></div>
|
|
||||||
</div>
|
|
||||||
</BODY>
|
|
||||||
</html>
|
|
24
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/testdata/page3.html
generated
vendored
24
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/testdata/page3.html
generated
vendored
|
@ -1,24 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>Tests for siblings</title>
|
|
||||||
</head>
|
|
||||||
<BODY>
|
|
||||||
<div id="main">
|
|
||||||
<div id="n1" class="one even row">hello</div>
|
|
||||||
<div id="n2" class="two odd row"></div>
|
|
||||||
<div id="n3" class="three even row"></div>
|
|
||||||
<div id="n4" class="four odd row"></div>
|
|
||||||
<div id="n5" class="five even row"></div>
|
|
||||||
<div id="n6" class="six odd row"></div>
|
|
||||||
</div>
|
|
||||||
<div id="foot">
|
|
||||||
<div id="nf1" class="one even row">text</div>
|
|
||||||
<div id="nf2" class="two odd row"></div>
|
|
||||||
<div id="nf3" class="three even row"></div>
|
|
||||||
<div id="nf4" class="four odd row"></div>
|
|
||||||
<div id="nf5" class="five even row odder"></div>
|
|
||||||
<div id="nf6" class="six odd row"></div>
|
|
||||||
</div>
|
|
||||||
</BODY>
|
|
||||||
</html>
|
|
697
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/traversal_test.go
generated
vendored
697
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/traversal_test.go
generated
vendored
|
@ -1,697 +0,0 @@
|
||||||
package goquery
|
|
||||||
|
|
||||||
import (
|
|
||||||
"strings"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestFind(t *testing.T) {
|
|
||||||
sel := Doc().Find("div.row-fluid")
|
|
||||||
assertLength(t, sel.Nodes, 9)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFindRollback(t *testing.T) {
|
|
||||||
sel := Doc().Find("div.row-fluid")
|
|
||||||
sel2 := sel.Find("a").End()
|
|
||||||
assertEqual(t, sel, sel2)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFindNotSelf(t *testing.T) {
|
|
||||||
sel := Doc().Find("h1").Find("h1")
|
|
||||||
assertLength(t, sel.Nodes, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFindInvalidSelector(t *testing.T) {
|
|
||||||
defer assertPanic(t)
|
|
||||||
Doc().Find(":+ ^")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestChainedFind(t *testing.T) {
|
|
||||||
sel := Doc().Find("div.hero-unit").Find(".row-fluid")
|
|
||||||
assertLength(t, sel.Nodes, 4)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestChildren(t *testing.T) {
|
|
||||||
sel := Doc().Find(".pvk-content").Children()
|
|
||||||
assertLength(t, sel.Nodes, 5)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestChildrenRollback(t *testing.T) {
|
|
||||||
sel := Doc().Find(".pvk-content")
|
|
||||||
sel2 := sel.Children().End()
|
|
||||||
assertEqual(t, sel, sel2)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestContents(t *testing.T) {
|
|
||||||
sel := Doc().Find(".pvk-content").Contents()
|
|
||||||
assertLength(t, sel.Nodes, 13)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestContentsRollback(t *testing.T) {
|
|
||||||
sel := Doc().Find(".pvk-content")
|
|
||||||
sel2 := sel.Contents().End()
|
|
||||||
assertEqual(t, sel, sel2)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestChildrenFiltered(t *testing.T) {
|
|
||||||
sel := Doc().Find(".pvk-content").ChildrenFiltered(".hero-unit")
|
|
||||||
assertLength(t, sel.Nodes, 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestChildrenFilteredRollback(t *testing.T) {
|
|
||||||
sel := Doc().Find(".pvk-content")
|
|
||||||
sel2 := sel.ChildrenFiltered(".hero-unit").End()
|
|
||||||
assertEqual(t, sel, sel2)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestContentsFiltered(t *testing.T) {
|
|
||||||
sel := Doc().Find(".pvk-content").ContentsFiltered(".hero-unit")
|
|
||||||
assertLength(t, sel.Nodes, 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestContentsFilteredRollback(t *testing.T) {
|
|
||||||
sel := Doc().Find(".pvk-content")
|
|
||||||
sel2 := sel.ContentsFiltered(".hero-unit").End()
|
|
||||||
assertEqual(t, sel, sel2)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestChildrenFilteredNone(t *testing.T) {
|
|
||||||
sel := Doc().Find(".pvk-content").ChildrenFiltered("a.btn")
|
|
||||||
assertLength(t, sel.Nodes, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestParent(t *testing.T) {
|
|
||||||
sel := Doc().Find(".container-fluid").Parent()
|
|
||||||
assertLength(t, sel.Nodes, 3)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestParentRollback(t *testing.T) {
|
|
||||||
sel := Doc().Find(".container-fluid")
|
|
||||||
sel2 := sel.Parent().End()
|
|
||||||
assertEqual(t, sel, sel2)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestParentBody(t *testing.T) {
|
|
||||||
sel := Doc().Find("body").Parent()
|
|
||||||
assertLength(t, sel.Nodes, 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestParentFiltered(t *testing.T) {
|
|
||||||
sel := Doc().Find(".container-fluid").ParentFiltered(".hero-unit")
|
|
||||||
assertLength(t, sel.Nodes, 1)
|
|
||||||
assertClass(t, sel, "hero-unit")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestParentFilteredRollback(t *testing.T) {
|
|
||||||
sel := Doc().Find(".container-fluid")
|
|
||||||
sel2 := sel.ParentFiltered(".hero-unit").End()
|
|
||||||
assertEqual(t, sel, sel2)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestParents(t *testing.T) {
|
|
||||||
sel := Doc().Find(".container-fluid").Parents()
|
|
||||||
assertLength(t, sel.Nodes, 8)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestParentsOrder(t *testing.T) {
|
|
||||||
sel := Doc().Find("#cf2").Parents()
|
|
||||||
assertLength(t, sel.Nodes, 6)
|
|
||||||
assertSelectionIs(t, sel, ".hero-unit", ".pvk-content", "div.row-fluid", "#cf1", "body", "html")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestParentsRollback(t *testing.T) {
|
|
||||||
sel := Doc().Find(".container-fluid")
|
|
||||||
sel2 := sel.Parents().End()
|
|
||||||
assertEqual(t, sel, sel2)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestParentsFiltered(t *testing.T) {
|
|
||||||
sel := Doc().Find(".container-fluid").ParentsFiltered("body")
|
|
||||||
assertLength(t, sel.Nodes, 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestParentsFilteredRollback(t *testing.T) {
|
|
||||||
sel := Doc().Find(".container-fluid")
|
|
||||||
sel2 := sel.ParentsFiltered("body").End()
|
|
||||||
assertEqual(t, sel, sel2)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestParentsUntil(t *testing.T) {
|
|
||||||
sel := Doc().Find(".container-fluid").ParentsUntil("body")
|
|
||||||
assertLength(t, sel.Nodes, 6)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestParentsUntilRollback(t *testing.T) {
|
|
||||||
sel := Doc().Find(".container-fluid")
|
|
||||||
sel2 := sel.ParentsUntil("body").End()
|
|
||||||
assertEqual(t, sel, sel2)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestParentsUntilSelection(t *testing.T) {
|
|
||||||
sel := Doc().Find(".container-fluid")
|
|
||||||
sel2 := Doc().Find(".pvk-content")
|
|
||||||
sel = sel.ParentsUntilSelection(sel2)
|
|
||||||
assertLength(t, sel.Nodes, 3)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestParentsUntilSelectionRollback(t *testing.T) {
|
|
||||||
sel := Doc().Find(".container-fluid")
|
|
||||||
sel2 := Doc().Find(".pvk-content")
|
|
||||||
sel2 = sel.ParentsUntilSelection(sel2).End()
|
|
||||||
assertEqual(t, sel, sel2)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestParentsUntilNodes(t *testing.T) {
|
|
||||||
sel := Doc().Find(".container-fluid")
|
|
||||||
sel2 := Doc().Find(".pvk-content, .hero-unit")
|
|
||||||
sel = sel.ParentsUntilNodes(sel2.Nodes...)
|
|
||||||
assertLength(t, sel.Nodes, 2)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestParentsUntilNodesRollback(t *testing.T) {
|
|
||||||
sel := Doc().Find(".container-fluid")
|
|
||||||
sel2 := Doc().Find(".pvk-content, .hero-unit")
|
|
||||||
sel2 = sel.ParentsUntilNodes(sel2.Nodes...).End()
|
|
||||||
assertEqual(t, sel, sel2)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestParentsFilteredUntil(t *testing.T) {
|
|
||||||
sel := Doc().Find(".container-fluid").ParentsFilteredUntil(".pvk-content", "body")
|
|
||||||
assertLength(t, sel.Nodes, 2)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestParentsFilteredUntilRollback(t *testing.T) {
|
|
||||||
sel := Doc().Find(".container-fluid")
|
|
||||||
sel2 := sel.ParentsFilteredUntil(".pvk-content", "body").End()
|
|
||||||
assertEqual(t, sel, sel2)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestParentsFilteredUntilSelection(t *testing.T) {
|
|
||||||
sel := Doc().Find(".container-fluid")
|
|
||||||
sel2 := Doc().Find(".row-fluid")
|
|
||||||
sel = sel.ParentsFilteredUntilSelection("div", sel2)
|
|
||||||
assertLength(t, sel.Nodes, 3)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestParentsFilteredUntilSelectionRollback(t *testing.T) {
|
|
||||||
sel := Doc().Find(".container-fluid")
|
|
||||||
sel2 := Doc().Find(".row-fluid")
|
|
||||||
sel2 = sel.ParentsFilteredUntilSelection("div", sel2).End()
|
|
||||||
assertEqual(t, sel, sel2)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestParentsFilteredUntilNodes(t *testing.T) {
|
|
||||||
sel := Doc().Find(".container-fluid")
|
|
||||||
sel2 := Doc().Find(".row-fluid")
|
|
||||||
sel = sel.ParentsFilteredUntilNodes("body", sel2.Nodes...)
|
|
||||||
assertLength(t, sel.Nodes, 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestParentsFilteredUntilNodesRollback(t *testing.T) {
|
|
||||||
sel := Doc().Find(".container-fluid")
|
|
||||||
sel2 := Doc().Find(".row-fluid")
|
|
||||||
sel2 = sel.ParentsFilteredUntilNodes("body", sel2.Nodes...).End()
|
|
||||||
assertEqual(t, sel, sel2)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSiblings(t *testing.T) {
|
|
||||||
sel := Doc().Find("h1").Siblings()
|
|
||||||
assertLength(t, sel.Nodes, 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSiblingsRollback(t *testing.T) {
|
|
||||||
sel := Doc().Find("h1")
|
|
||||||
sel2 := sel.Siblings().End()
|
|
||||||
assertEqual(t, sel, sel2)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSiblings2(t *testing.T) {
|
|
||||||
sel := Doc().Find(".pvk-gutter").Siblings()
|
|
||||||
assertLength(t, sel.Nodes, 9)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSiblings3(t *testing.T) {
|
|
||||||
sel := Doc().Find("body>.container-fluid").Siblings()
|
|
||||||
assertLength(t, sel.Nodes, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSiblingsFiltered(t *testing.T) {
|
|
||||||
sel := Doc().Find(".pvk-gutter").SiblingsFiltered(".pvk-content")
|
|
||||||
assertLength(t, sel.Nodes, 3)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSiblingsFilteredRollback(t *testing.T) {
|
|
||||||
sel := Doc().Find(".pvk-gutter")
|
|
||||||
sel2 := sel.SiblingsFiltered(".pvk-content").End()
|
|
||||||
assertEqual(t, sel, sel2)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestNext(t *testing.T) {
|
|
||||||
sel := Doc().Find("h1").Next()
|
|
||||||
assertLength(t, sel.Nodes, 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestNextRollback(t *testing.T) {
|
|
||||||
sel := Doc().Find("h1")
|
|
||||||
sel2 := sel.Next().End()
|
|
||||||
assertEqual(t, sel, sel2)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestNext2(t *testing.T) {
|
|
||||||
sel := Doc().Find(".close").Next()
|
|
||||||
assertLength(t, sel.Nodes, 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestNextNone(t *testing.T) {
|
|
||||||
sel := Doc().Find("small").Next()
|
|
||||||
assertLength(t, sel.Nodes, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestNextFiltered(t *testing.T) {
|
|
||||||
sel := Doc().Find(".container-fluid").NextFiltered("div")
|
|
||||||
assertLength(t, sel.Nodes, 2)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestNextFilteredRollback(t *testing.T) {
|
|
||||||
sel := Doc().Find(".container-fluid")
|
|
||||||
sel2 := sel.NextFiltered("div").End()
|
|
||||||
assertEqual(t, sel, sel2)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestNextFiltered2(t *testing.T) {
|
|
||||||
sel := Doc().Find(".container-fluid").NextFiltered("[ng-view]")
|
|
||||||
assertLength(t, sel.Nodes, 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestPrev(t *testing.T) {
|
|
||||||
sel := Doc().Find(".red").Prev()
|
|
||||||
assertLength(t, sel.Nodes, 1)
|
|
||||||
assertClass(t, sel, "green")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestPrevRollback(t *testing.T) {
|
|
||||||
sel := Doc().Find(".red")
|
|
||||||
sel2 := sel.Prev().End()
|
|
||||||
assertEqual(t, sel, sel2)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestPrev2(t *testing.T) {
|
|
||||||
sel := Doc().Find(".row-fluid").Prev()
|
|
||||||
assertLength(t, sel.Nodes, 5)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestPrevNone(t *testing.T) {
|
|
||||||
sel := Doc().Find("h2").Prev()
|
|
||||||
assertLength(t, sel.Nodes, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestPrevFiltered(t *testing.T) {
|
|
||||||
sel := Doc().Find(".row-fluid").PrevFiltered(".row-fluid")
|
|
||||||
assertLength(t, sel.Nodes, 5)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestPrevFilteredRollback(t *testing.T) {
|
|
||||||
sel := Doc().Find(".row-fluid")
|
|
||||||
sel2 := sel.PrevFiltered(".row-fluid").End()
|
|
||||||
assertEqual(t, sel, sel2)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestNextAll(t *testing.T) {
|
|
||||||
sel := Doc().Find("#cf2 div:nth-child(1)").NextAll()
|
|
||||||
assertLength(t, sel.Nodes, 3)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestNextAllRollback(t *testing.T) {
|
|
||||||
sel := Doc().Find("#cf2 div:nth-child(1)")
|
|
||||||
sel2 := sel.NextAll().End()
|
|
||||||
assertEqual(t, sel, sel2)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestNextAll2(t *testing.T) {
|
|
||||||
sel := Doc().Find("div[ng-cloak]").NextAll()
|
|
||||||
assertLength(t, sel.Nodes, 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestNextAllNone(t *testing.T) {
|
|
||||||
sel := Doc().Find(".footer").NextAll()
|
|
||||||
assertLength(t, sel.Nodes, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestNextAllFiltered(t *testing.T) {
|
|
||||||
sel := Doc().Find("#cf2 .row-fluid").NextAllFiltered("[ng-cloak]")
|
|
||||||
assertLength(t, sel.Nodes, 2)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestNextAllFilteredRollback(t *testing.T) {
|
|
||||||
sel := Doc().Find("#cf2 .row-fluid")
|
|
||||||
sel2 := sel.NextAllFiltered("[ng-cloak]").End()
|
|
||||||
assertEqual(t, sel, sel2)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestNextAllFiltered2(t *testing.T) {
|
|
||||||
sel := Doc().Find(".close").NextAllFiltered("h4")
|
|
||||||
assertLength(t, sel.Nodes, 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestPrevAll(t *testing.T) {
|
|
||||||
sel := Doc().Find("[ng-view]").PrevAll()
|
|
||||||
assertLength(t, sel.Nodes, 2)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestPrevAllOrder(t *testing.T) {
|
|
||||||
sel := Doc().Find("[ng-view]").PrevAll()
|
|
||||||
assertLength(t, sel.Nodes, 2)
|
|
||||||
assertSelectionIs(t, sel, "#cf4", "#cf3")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestPrevAllRollback(t *testing.T) {
|
|
||||||
sel := Doc().Find("[ng-view]")
|
|
||||||
sel2 := sel.PrevAll().End()
|
|
||||||
assertEqual(t, sel, sel2)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestPrevAll2(t *testing.T) {
|
|
||||||
sel := Doc().Find(".pvk-gutter").PrevAll()
|
|
||||||
assertLength(t, sel.Nodes, 6)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestPrevAllFiltered(t *testing.T) {
|
|
||||||
sel := Doc().Find(".pvk-gutter").PrevAllFiltered(".pvk-content")
|
|
||||||
assertLength(t, sel.Nodes, 3)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestPrevAllFilteredRollback(t *testing.T) {
|
|
||||||
sel := Doc().Find(".pvk-gutter")
|
|
||||||
sel2 := sel.PrevAllFiltered(".pvk-content").End()
|
|
||||||
assertEqual(t, sel, sel2)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestNextUntil(t *testing.T) {
|
|
||||||
sel := Doc().Find(".alert a").NextUntil("p")
|
|
||||||
assertLength(t, sel.Nodes, 1)
|
|
||||||
assertSelectionIs(t, sel, "h4")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestNextUntil2(t *testing.T) {
|
|
||||||
sel := Doc().Find("#cf2-1").NextUntil("[ng-cloak]")
|
|
||||||
assertLength(t, sel.Nodes, 1)
|
|
||||||
assertSelectionIs(t, sel, "#cf2-2")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestNextUntilOrder(t *testing.T) {
|
|
||||||
sel := Doc().Find("#cf2-1").NextUntil("#cf2-4")
|
|
||||||
assertLength(t, sel.Nodes, 2)
|
|
||||||
assertSelectionIs(t, sel, "#cf2-2", "#cf2-3")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestNextUntilRollback(t *testing.T) {
|
|
||||||
sel := Doc().Find("#cf2-1")
|
|
||||||
sel2 := sel.PrevUntil("#cf2-4").End()
|
|
||||||
assertEqual(t, sel, sel2)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestNextUntilSelection(t *testing.T) {
|
|
||||||
sel := Doc2().Find("#n2")
|
|
||||||
sel2 := Doc2().Find("#n4")
|
|
||||||
sel2 = sel.NextUntilSelection(sel2)
|
|
||||||
assertLength(t, sel2.Nodes, 1)
|
|
||||||
assertSelectionIs(t, sel2, "#n3")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestNextUntilSelectionRollback(t *testing.T) {
|
|
||||||
sel := Doc2().Find("#n2")
|
|
||||||
sel2 := Doc2().Find("#n4")
|
|
||||||
sel2 = sel.NextUntilSelection(sel2).End()
|
|
||||||
assertEqual(t, sel, sel2)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestNextUntilNodes(t *testing.T) {
|
|
||||||
sel := Doc2().Find("#n2")
|
|
||||||
sel2 := Doc2().Find("#n5")
|
|
||||||
sel2 = sel.NextUntilNodes(sel2.Nodes...)
|
|
||||||
assertLength(t, sel2.Nodes, 2)
|
|
||||||
assertSelectionIs(t, sel2, "#n3", "#n4")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestNextUntilNodesRollback(t *testing.T) {
|
|
||||||
sel := Doc2().Find("#n2")
|
|
||||||
sel2 := Doc2().Find("#n5")
|
|
||||||
sel2 = sel.NextUntilNodes(sel2.Nodes...).End()
|
|
||||||
assertEqual(t, sel, sel2)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestPrevUntil(t *testing.T) {
|
|
||||||
sel := Doc().Find(".alert p").PrevUntil("a")
|
|
||||||
assertLength(t, sel.Nodes, 1)
|
|
||||||
assertSelectionIs(t, sel, "h4")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestPrevUntil2(t *testing.T) {
|
|
||||||
sel := Doc().Find("[ng-cloak]").PrevUntil(":not([ng-cloak])")
|
|
||||||
assertLength(t, sel.Nodes, 1)
|
|
||||||
assertSelectionIs(t, sel, "[ng-cloak]")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestPrevUntilOrder(t *testing.T) {
|
|
||||||
sel := Doc().Find("#cf2-4").PrevUntil("#cf2-1")
|
|
||||||
assertLength(t, sel.Nodes, 2)
|
|
||||||
assertSelectionIs(t, sel, "#cf2-3", "#cf2-2")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestPrevUntilRollback(t *testing.T) {
|
|
||||||
sel := Doc().Find("#cf2-4")
|
|
||||||
sel2 := sel.PrevUntil("#cf2-1").End()
|
|
||||||
assertEqual(t, sel, sel2)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestPrevUntilSelection(t *testing.T) {
|
|
||||||
sel := Doc2().Find("#n4")
|
|
||||||
sel2 := Doc2().Find("#n2")
|
|
||||||
sel2 = sel.PrevUntilSelection(sel2)
|
|
||||||
assertLength(t, sel2.Nodes, 1)
|
|
||||||
assertSelectionIs(t, sel2, "#n3")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestPrevUntilSelectionRollback(t *testing.T) {
|
|
||||||
sel := Doc2().Find("#n4")
|
|
||||||
sel2 := Doc2().Find("#n2")
|
|
||||||
sel2 = sel.PrevUntilSelection(sel2).End()
|
|
||||||
assertEqual(t, sel, sel2)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestPrevUntilNodes(t *testing.T) {
|
|
||||||
sel := Doc2().Find("#n5")
|
|
||||||
sel2 := Doc2().Find("#n2")
|
|
||||||
sel2 = sel.PrevUntilNodes(sel2.Nodes...)
|
|
||||||
assertLength(t, sel2.Nodes, 2)
|
|
||||||
assertSelectionIs(t, sel2, "#n4", "#n3")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestPrevUntilNodesRollback(t *testing.T) {
|
|
||||||
sel := Doc2().Find("#n5")
|
|
||||||
sel2 := Doc2().Find("#n2")
|
|
||||||
sel2 = sel.PrevUntilNodes(sel2.Nodes...).End()
|
|
||||||
assertEqual(t, sel, sel2)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestNextFilteredUntil(t *testing.T) {
|
|
||||||
sel := Doc2().Find(".two").NextFilteredUntil(".even", ".six")
|
|
||||||
assertLength(t, sel.Nodes, 4)
|
|
||||||
assertSelectionIs(t, sel, "#n3", "#n5", "#nf3", "#nf5")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestNextFilteredUntilRollback(t *testing.T) {
|
|
||||||
sel := Doc2().Find(".two")
|
|
||||||
sel2 := sel.NextFilteredUntil(".even", ".six").End()
|
|
||||||
assertEqual(t, sel, sel2)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestNextFilteredUntilSelection(t *testing.T) {
|
|
||||||
sel := Doc2().Find(".even")
|
|
||||||
sel2 := Doc2().Find(".five")
|
|
||||||
sel = sel.NextFilteredUntilSelection(".even", sel2)
|
|
||||||
assertLength(t, sel.Nodes, 2)
|
|
||||||
assertSelectionIs(t, sel, "#n3", "#nf3")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestNextFilteredUntilSelectionRollback(t *testing.T) {
|
|
||||||
sel := Doc2().Find(".even")
|
|
||||||
sel2 := Doc2().Find(".five")
|
|
||||||
sel3 := sel.NextFilteredUntilSelection(".even", sel2).End()
|
|
||||||
assertEqual(t, sel, sel3)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestNextFilteredUntilNodes(t *testing.T) {
|
|
||||||
sel := Doc2().Find(".even")
|
|
||||||
sel2 := Doc2().Find(".four")
|
|
||||||
sel = sel.NextFilteredUntilNodes(".odd", sel2.Nodes...)
|
|
||||||
assertLength(t, sel.Nodes, 4)
|
|
||||||
assertSelectionIs(t, sel, "#n2", "#n6", "#nf2", "#nf6")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestNextFilteredUntilNodesRollback(t *testing.T) {
|
|
||||||
sel := Doc2().Find(".even")
|
|
||||||
sel2 := Doc2().Find(".four")
|
|
||||||
sel3 := sel.NextFilteredUntilNodes(".odd", sel2.Nodes...).End()
|
|
||||||
assertEqual(t, sel, sel3)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestPrevFilteredUntil(t *testing.T) {
|
|
||||||
sel := Doc2().Find(".five").PrevFilteredUntil(".odd", ".one")
|
|
||||||
assertLength(t, sel.Nodes, 4)
|
|
||||||
assertSelectionIs(t, sel, "#n4", "#n2", "#nf4", "#nf2")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestPrevFilteredUntilRollback(t *testing.T) {
|
|
||||||
sel := Doc2().Find(".four")
|
|
||||||
sel2 := sel.PrevFilteredUntil(".odd", ".one").End()
|
|
||||||
assertEqual(t, sel, sel2)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestPrevFilteredUntilSelection(t *testing.T) {
|
|
||||||
sel := Doc2().Find(".odd")
|
|
||||||
sel2 := Doc2().Find(".two")
|
|
||||||
sel = sel.PrevFilteredUntilSelection(".odd", sel2)
|
|
||||||
assertLength(t, sel.Nodes, 2)
|
|
||||||
assertSelectionIs(t, sel, "#n4", "#nf4")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestPrevFilteredUntilSelectionRollback(t *testing.T) {
|
|
||||||
sel := Doc2().Find(".even")
|
|
||||||
sel2 := Doc2().Find(".five")
|
|
||||||
sel3 := sel.PrevFilteredUntilSelection(".even", sel2).End()
|
|
||||||
assertEqual(t, sel, sel3)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestPrevFilteredUntilNodes(t *testing.T) {
|
|
||||||
sel := Doc2().Find(".even")
|
|
||||||
sel2 := Doc2().Find(".four")
|
|
||||||
sel = sel.PrevFilteredUntilNodes(".odd", sel2.Nodes...)
|
|
||||||
assertLength(t, sel.Nodes, 2)
|
|
||||||
assertSelectionIs(t, sel, "#n2", "#nf2")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestPrevFilteredUntilNodesRollback(t *testing.T) {
|
|
||||||
sel := Doc2().Find(".even")
|
|
||||||
sel2 := Doc2().Find(".four")
|
|
||||||
sel3 := sel.PrevFilteredUntilNodes(".odd", sel2.Nodes...).End()
|
|
||||||
assertEqual(t, sel, sel3)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestClosestItself(t *testing.T) {
|
|
||||||
sel := Doc2().Find(".three")
|
|
||||||
sel2 := sel.Closest(".row")
|
|
||||||
assertLength(t, sel2.Nodes, sel.Length())
|
|
||||||
assertSelectionIs(t, sel2, "#n3", "#nf3")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestClosestNoDupes(t *testing.T) {
|
|
||||||
sel := Doc().Find(".span12")
|
|
||||||
sel2 := sel.Closest(".pvk-content")
|
|
||||||
assertLength(t, sel2.Nodes, 1)
|
|
||||||
assertClass(t, sel2, "pvk-content")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestClosestNone(t *testing.T) {
|
|
||||||
sel := Doc().Find("h4")
|
|
||||||
sel2 := sel.Closest("a")
|
|
||||||
assertLength(t, sel2.Nodes, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestClosestMany(t *testing.T) {
|
|
||||||
sel := Doc().Find(".container-fluid")
|
|
||||||
sel2 := sel.Closest(".pvk-content")
|
|
||||||
assertLength(t, sel2.Nodes, 2)
|
|
||||||
assertSelectionIs(t, sel2, "#pc1", "#pc2")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestClosestRollback(t *testing.T) {
|
|
||||||
sel := Doc().Find(".container-fluid")
|
|
||||||
sel2 := sel.Closest(".pvk-content").End()
|
|
||||||
assertEqual(t, sel, sel2)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestClosestSelectionItself(t *testing.T) {
|
|
||||||
sel := Doc2().Find(".three")
|
|
||||||
sel2 := sel.ClosestSelection(Doc2().Find(".row"))
|
|
||||||
assertLength(t, sel2.Nodes, sel.Length())
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestClosestSelectionNoDupes(t *testing.T) {
|
|
||||||
sel := Doc().Find(".span12")
|
|
||||||
sel2 := sel.ClosestSelection(Doc().Find(".pvk-content"))
|
|
||||||
assertLength(t, sel2.Nodes, 1)
|
|
||||||
assertClass(t, sel2, "pvk-content")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestClosestSelectionNone(t *testing.T) {
|
|
||||||
sel := Doc().Find("h4")
|
|
||||||
sel2 := sel.ClosestSelection(Doc().Find("a"))
|
|
||||||
assertLength(t, sel2.Nodes, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestClosestSelectionMany(t *testing.T) {
|
|
||||||
sel := Doc().Find(".container-fluid")
|
|
||||||
sel2 := sel.ClosestSelection(Doc().Find(".pvk-content"))
|
|
||||||
assertLength(t, sel2.Nodes, 2)
|
|
||||||
assertSelectionIs(t, sel2, "#pc1", "#pc2")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestClosestSelectionRollback(t *testing.T) {
|
|
||||||
sel := Doc().Find(".container-fluid")
|
|
||||||
sel2 := sel.ClosestSelection(Doc().Find(".pvk-content")).End()
|
|
||||||
assertEqual(t, sel, sel2)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestClosestNodesItself(t *testing.T) {
|
|
||||||
sel := Doc2().Find(".three")
|
|
||||||
sel2 := sel.ClosestNodes(Doc2().Find(".row").Nodes...)
|
|
||||||
assertLength(t, sel2.Nodes, sel.Length())
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestClosestNodesNoDupes(t *testing.T) {
|
|
||||||
sel := Doc().Find(".span12")
|
|
||||||
sel2 := sel.ClosestNodes(Doc().Find(".pvk-content").Nodes...)
|
|
||||||
assertLength(t, sel2.Nodes, 1)
|
|
||||||
assertClass(t, sel2, "pvk-content")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestClosestNodesNone(t *testing.T) {
|
|
||||||
sel := Doc().Find("h4")
|
|
||||||
sel2 := sel.ClosestNodes(Doc().Find("a").Nodes...)
|
|
||||||
assertLength(t, sel2.Nodes, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestClosestNodesMany(t *testing.T) {
|
|
||||||
sel := Doc().Find(".container-fluid")
|
|
||||||
sel2 := sel.ClosestNodes(Doc().Find(".pvk-content").Nodes...)
|
|
||||||
assertLength(t, sel2.Nodes, 2)
|
|
||||||
assertSelectionIs(t, sel2, "#pc1", "#pc2")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestClosestNodesRollback(t *testing.T) {
|
|
||||||
sel := Doc().Find(".container-fluid")
|
|
||||||
sel2 := sel.ClosestNodes(Doc().Find(".pvk-content").Nodes...).End()
|
|
||||||
assertEqual(t, sel, sel2)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestIssue26(t *testing.T) {
|
|
||||||
img1 := `<img src="assets/images/gallery/thumb-1.jpg" alt="150x150" />`
|
|
||||||
img2 := `<img alt="150x150" src="assets/images/gallery/thumb-1.jpg" />`
|
|
||||||
cases := []struct {
|
|
||||||
s string
|
|
||||||
l int
|
|
||||||
}{
|
|
||||||
{s: img1 + img2, l: 2},
|
|
||||||
{s: img1, l: 1},
|
|
||||||
{s: img2, l: 1},
|
|
||||||
}
|
|
||||||
for _, c := range cases {
|
|
||||||
doc, err := NewDocumentFromReader(strings.NewReader(c.s))
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
sel := doc.Find("img[src]")
|
|
||||||
assertLength(t, sel.Nodes, c.l)
|
|
||||||
}
|
|
||||||
}
|
|
192
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/type_test.go
generated
vendored
192
Godeps/_workspace/src/github.com/PuerkitoBio/goquery/type_test.go
generated
vendored
|
@ -1,192 +0,0 @@
|
||||||
package goquery
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"golang.org/x/net/html"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Test helper functions and members
|
|
||||||
var doc *Document
|
|
||||||
var doc2 *Document
|
|
||||||
var doc3 *Document
|
|
||||||
var docB *Document
|
|
||||||
var docW *Document
|
|
||||||
|
|
||||||
func Doc() *Document {
|
|
||||||
if doc == nil {
|
|
||||||
doc = loadDoc("page.html")
|
|
||||||
}
|
|
||||||
return doc
|
|
||||||
}
|
|
||||||
func DocClone() *Document {
|
|
||||||
return CloneDocument(Doc())
|
|
||||||
}
|
|
||||||
func Doc2() *Document {
|
|
||||||
if doc2 == nil {
|
|
||||||
doc2 = loadDoc("page2.html")
|
|
||||||
}
|
|
||||||
return doc2
|
|
||||||
}
|
|
||||||
func Doc2Clone() *Document {
|
|
||||||
return CloneDocument(Doc2())
|
|
||||||
}
|
|
||||||
func Doc3() *Document {
|
|
||||||
if doc3 == nil {
|
|
||||||
doc3 = loadDoc("page3.html")
|
|
||||||
}
|
|
||||||
return doc3
|
|
||||||
}
|
|
||||||
func Doc3Clone() *Document {
|
|
||||||
return CloneDocument(Doc3())
|
|
||||||
}
|
|
||||||
func DocB() *Document {
|
|
||||||
if docB == nil {
|
|
||||||
docB = loadDoc("gotesting.html")
|
|
||||||
}
|
|
||||||
return docB
|
|
||||||
}
|
|
||||||
func DocBClone() *Document {
|
|
||||||
return CloneDocument(DocB())
|
|
||||||
}
|
|
||||||
func DocW() *Document {
|
|
||||||
if docW == nil {
|
|
||||||
docW = loadDoc("gowiki.html")
|
|
||||||
}
|
|
||||||
return docW
|
|
||||||
}
|
|
||||||
func DocWClone() *Document {
|
|
||||||
return CloneDocument(DocW())
|
|
||||||
}
|
|
||||||
|
|
||||||
func assertLength(t *testing.T, nodes []*html.Node, length int) {
|
|
||||||
if len(nodes) != length {
|
|
||||||
t.Errorf("Expected %d nodes, found %d.", length, len(nodes))
|
|
||||||
for i, n := range nodes {
|
|
||||||
t.Logf("Node %d: %+v.", i, n)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func assertClass(t *testing.T, sel *Selection, class string) {
|
|
||||||
if !sel.HasClass(class) {
|
|
||||||
t.Errorf("Expected node to have class %s, found %+v.", class, sel.Get(0))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func assertPanic(t *testing.T) {
|
|
||||||
if e := recover(); e == nil {
|
|
||||||
t.Error("Expected a panic.")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func assertEqual(t *testing.T, s1 *Selection, s2 *Selection) {
|
|
||||||
if s1 != s2 {
|
|
||||||
t.Error("Expected selection objects to be the same.")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func assertSelectionIs(t *testing.T, sel *Selection, is ...string) {
|
|
||||||
for i := 0; i < sel.Length(); i++ {
|
|
||||||
if !sel.Eq(i).Is(is[i]) {
|
|
||||||
t.Errorf("Expected node %d to be %s, found %+v", i, is[i], sel.Get(i))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func printSel(t *testing.T, sel *Selection) {
|
|
||||||
if testing.Verbose() {
|
|
||||||
h, err := sel.Html()
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
t.Log(h)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func loadDoc(page string) *Document {
|
|
||||||
var f *os.File
|
|
||||||
var e error
|
|
||||||
|
|
||||||
if f, e = os.Open(fmt.Sprintf("./testdata/%s", page)); e != nil {
|
|
||||||
panic(e.Error())
|
|
||||||
}
|
|
||||||
defer f.Close()
|
|
||||||
|
|
||||||
var node *html.Node
|
|
||||||
if node, e = html.Parse(f); e != nil {
|
|
||||||
panic(e.Error())
|
|
||||||
}
|
|
||||||
return NewDocumentFromNode(node)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestNewDocument(t *testing.T) {
|
|
||||||
if f, e := os.Open("./testdata/page.html"); e != nil {
|
|
||||||
t.Error(e.Error())
|
|
||||||
} else {
|
|
||||||
defer f.Close()
|
|
||||||
if node, e := html.Parse(f); e != nil {
|
|
||||||
t.Error(e.Error())
|
|
||||||
} else {
|
|
||||||
doc = NewDocumentFromNode(node)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestNewDocumentFromReader(t *testing.T) {
|
|
||||||
cases := []struct {
|
|
||||||
src string
|
|
||||||
err bool
|
|
||||||
sel string
|
|
||||||
cnt int
|
|
||||||
}{
|
|
||||||
0: {
|
|
||||||
src: `
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>Test</title>
|
|
||||||
<body>
|
|
||||||
<h1>Hi</h1>
|
|
||||||
</body>
|
|
||||||
</html>`,
|
|
||||||
sel: "h1",
|
|
||||||
cnt: 1,
|
|
||||||
},
|
|
||||||
1: {
|
|
||||||
// Actually pretty hard to make html.Parse return an error
|
|
||||||
// based on content...
|
|
||||||
src: `<html><body><aef<eqf>>>qq></body></ht>`,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
buf := bytes.NewBuffer(nil)
|
|
||||||
|
|
||||||
for i, c := range cases {
|
|
||||||
buf.Reset()
|
|
||||||
buf.WriteString(c.src)
|
|
||||||
|
|
||||||
d, e := NewDocumentFromReader(buf)
|
|
||||||
if (e != nil) != c.err {
|
|
||||||
if c.err {
|
|
||||||
t.Errorf("[%d] - expected error, got none", i)
|
|
||||||
} else {
|
|
||||||
t.Errorf("[%d] - expected no error, got %s", i, e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if c.sel != "" {
|
|
||||||
s := d.Find(c.sel)
|
|
||||||
if s.Length() != c.cnt {
|
|
||||||
t.Errorf("[%d] - expected %d nodes, found %d", i, c.cnt, s.Length())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestNewDocumentFromResponseNil(t *testing.T) {
|
|
||||||
_, e := NewDocumentFromResponse(nil)
|
|
||||||
if e == nil {
|
|
||||||
t.Error("Expected error, got none")
|
|
||||||
}
|
|
||||||
}
|
|
53
Godeps/_workspace/src/github.com/andybalholm/cascadia/benchmark_test.go
generated
vendored
53
Godeps/_workspace/src/github.com/andybalholm/cascadia/benchmark_test.go
generated
vendored
|
@ -1,53 +0,0 @@
|
||||||
package cascadia
|
|
||||||
|
|
||||||
import (
|
|
||||||
"strings"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"golang.org/x/net/html"
|
|
||||||
)
|
|
||||||
|
|
||||||
func MustParseHTML(doc string) *html.Node {
|
|
||||||
dom, err := html.Parse(strings.NewReader(doc))
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
return dom
|
|
||||||
}
|
|
||||||
|
|
||||||
var selector = MustCompile(`div.matched`)
|
|
||||||
var doc = `<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<body>
|
|
||||||
<div class="matched">
|
|
||||||
<div>
|
|
||||||
<div class="matched"></div>
|
|
||||||
<div class="matched"></div>
|
|
||||||
<div class="matched"></div>
|
|
||||||
<div class="matched"></div>
|
|
||||||
<div class="matched"></div>
|
|
||||||
<div class="matched"></div>
|
|
||||||
<div class="matched"></div>
|
|
||||||
<div class="matched"></div>
|
|
||||||
<div class="matched"></div>
|
|
||||||
<div class="matched"></div>
|
|
||||||
<div class="matched"></div>
|
|
||||||
<div class="matched"></div>
|
|
||||||
<div class="matched"></div>
|
|
||||||
<div class="matched"></div>
|
|
||||||
<div class="matched"></div>
|
|
||||||
<div class="matched"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
`
|
|
||||||
var dom = MustParseHTML(doc)
|
|
||||||
|
|
||||||
func BenchmarkMatchAll(b *testing.B) {
|
|
||||||
var matches []*html.Node
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
matches = selector.MatchAll(dom)
|
|
||||||
}
|
|
||||||
_ = matches
|
|
||||||
}
|
|
86
Godeps/_workspace/src/github.com/andybalholm/cascadia/parser_test.go
generated
vendored
86
Godeps/_workspace/src/github.com/andybalholm/cascadia/parser_test.go
generated
vendored
|
@ -1,86 +0,0 @@
|
||||||
package cascadia
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
var identifierTests = map[string]string{
|
|
||||||
"x": "x",
|
|
||||||
"96": "",
|
|
||||||
"-x": "-x",
|
|
||||||
`r\e9 sumé`: "résumé",
|
|
||||||
`a\"b`: `a"b`,
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestParseIdentifier(t *testing.T) {
|
|
||||||
for source, want := range identifierTests {
|
|
||||||
p := &parser{s: source}
|
|
||||||
got, err := p.parseIdentifier()
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
if want == "" {
|
|
||||||
// It was supposed to be an error.
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
t.Errorf("parsing %q: got error (%s), want %q", source, err, want)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if want == "" {
|
|
||||||
if err == nil {
|
|
||||||
t.Errorf("parsing %q: got %q, want error", source, got)
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if p.i < len(source) {
|
|
||||||
t.Errorf("parsing %q: %d bytes left over", source, len(source)-p.i)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if got != want {
|
|
||||||
t.Errorf("parsing %q: got %q, want %q", source, got, want)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var stringTests = map[string]string{
|
|
||||||
`"x"`: "x",
|
|
||||||
`'x'`: "x",
|
|
||||||
`'x`: "",
|
|
||||||
"'x\\\r\nx'": "xx",
|
|
||||||
`"r\e9 sumé"`: "résumé",
|
|
||||||
`"a\"b"`: `a"b`,
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestParseString(t *testing.T) {
|
|
||||||
for source, want := range stringTests {
|
|
||||||
p := &parser{s: source}
|
|
||||||
got, err := p.parseString()
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
if want == "" {
|
|
||||||
// It was supposed to be an error.
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
t.Errorf("parsing %q: got error (%s), want %q", source, err, want)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if want == "" {
|
|
||||||
if err == nil {
|
|
||||||
t.Errorf("parsing %q: got %q, want error", source, got)
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if p.i < len(source) {
|
|
||||||
t.Errorf("parsing %q: %d bytes left over", source, len(source)-p.i)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if got != want {
|
|
||||||
t.Errorf("parsing %q: got %q, want %q", source, got, want)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
559
Godeps/_workspace/src/github.com/andybalholm/cascadia/selector_test.go
generated
vendored
559
Godeps/_workspace/src/github.com/andybalholm/cascadia/selector_test.go
generated
vendored
|
@ -1,559 +0,0 @@
|
||||||
package cascadia
|
|
||||||
|
|
||||||
import (
|
|
||||||
"strings"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"golang.org/x/net/html"
|
|
||||||
)
|
|
||||||
|
|
||||||
type selectorTest struct {
|
|
||||||
HTML, selector string
|
|
||||||
results []string
|
|
||||||
}
|
|
||||||
|
|
||||||
func nodeString(n *html.Node) string {
|
|
||||||
switch n.Type {
|
|
||||||
case html.TextNode:
|
|
||||||
return n.Data
|
|
||||||
case html.ElementNode:
|
|
||||||
return html.Token{
|
|
||||||
Type: html.StartTagToken,
|
|
||||||
Data: n.Data,
|
|
||||||
Attr: n.Attr,
|
|
||||||
}.String()
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
var selectorTests = []selectorTest{
|
|
||||||
{
|
|
||||||
`<body><address>This address...</address></body>`,
|
|
||||||
"address",
|
|
||||||
[]string{
|
|
||||||
"<address>",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
`<html><head></head><body></body></html>`,
|
|
||||||
"*",
|
|
||||||
[]string{
|
|
||||||
"",
|
|
||||||
"<html>",
|
|
||||||
"<head>",
|
|
||||||
"<body>",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
`<p id="foo"><p id="bar">`,
|
|
||||||
"#foo",
|
|
||||||
[]string{
|
|
||||||
`<p id="foo">`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
`<ul><li id="t1"><p id="t1">`,
|
|
||||||
"li#t1",
|
|
||||||
[]string{
|
|
||||||
`<li id="t1">`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
`<ol><li id="t4"><li id="t44">`,
|
|
||||||
"*#t4",
|
|
||||||
[]string{
|
|
||||||
`<li id="t4">`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
`<ul><li class="t1"><li class="t2">`,
|
|
||||||
".t1",
|
|
||||||
[]string{
|
|
||||||
`<li class="t1">`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
`<p class="t1 t2">`,
|
|
||||||
"p.t1",
|
|
||||||
[]string{
|
|
||||||
`<p class="t1 t2">`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
`<div class="test">`,
|
|
||||||
"div.teST",
|
|
||||||
[]string{},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
`<p class="t1 t2">`,
|
|
||||||
".t1.fail",
|
|
||||||
[]string{},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
`<p class="t1 t2">`,
|
|
||||||
"p.t1.t2",
|
|
||||||
[]string{
|
|
||||||
`<p class="t1 t2">`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
`<p><p title="title">`,
|
|
||||||
"p[title]",
|
|
||||||
[]string{
|
|
||||||
`<p title="title">`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
`<address><address title="foo"><address title="bar">`,
|
|
||||||
`address[title="foo"]`,
|
|
||||||
[]string{
|
|
||||||
`<address title="foo">`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
`<p title="tot foo bar">`,
|
|
||||||
`[ title ~= foo ]`,
|
|
||||||
[]string{
|
|
||||||
`<p title="tot foo bar">`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
`<p title="hello world">`,
|
|
||||||
`[title~="hello world"]`,
|
|
||||||
[]string{},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
`<p lang="en"><p lang="en-gb"><p lang="enough"><p lang="fr-en">`,
|
|
||||||
`[lang|="en"]`,
|
|
||||||
[]string{
|
|
||||||
`<p lang="en">`,
|
|
||||||
`<p lang="en-gb">`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
`<p title="foobar"><p title="barfoo">`,
|
|
||||||
`[title^="foo"]`,
|
|
||||||
[]string{
|
|
||||||
`<p title="foobar">`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
`<p title="foobar"><p title="barfoo">`,
|
|
||||||
`[title$="bar"]`,
|
|
||||||
[]string{
|
|
||||||
`<p title="foobar">`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
`<p title="foobarufoo">`,
|
|
||||||
`[title*="bar"]`,
|
|
||||||
[]string{
|
|
||||||
`<p title="foobarufoo">`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
`<p class="t1 t2">`,
|
|
||||||
".t1:not(.t2)",
|
|
||||||
[]string{},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
`<div class="t3">`,
|
|
||||||
`div:not(.t1)`,
|
|
||||||
[]string{
|
|
||||||
`<div class="t3">`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
`<ol><li id=1><li id=2><li id=3></ol>`,
|
|
||||||
`li:nth-child(odd)`,
|
|
||||||
[]string{
|
|
||||||
`<li id="1">`,
|
|
||||||
`<li id="3">`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
`<ol><li id=1><li id=2><li id=3></ol>`,
|
|
||||||
`li:nth-child(even)`,
|
|
||||||
[]string{
|
|
||||||
`<li id="2">`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
`<ol><li id=1><li id=2><li id=3></ol>`,
|
|
||||||
`li:nth-child(-n+2)`,
|
|
||||||
[]string{
|
|
||||||
`<li id="1">`,
|
|
||||||
`<li id="2">`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
`<ol><li id=1><li id=2><li id=3></ol>`,
|
|
||||||
`li:nth-child(3n+1)`,
|
|
||||||
[]string{
|
|
||||||
`<li id="1">`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
`<ol><li id=1><li id=2><li id=3><li id=4></ol>`,
|
|
||||||
`li:nth-last-child(odd)`,
|
|
||||||
[]string{
|
|
||||||
`<li id="2">`,
|
|
||||||
`<li id="4">`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
`<ol><li id=1><li id=2><li id=3><li id=4></ol>`,
|
|
||||||
`li:nth-last-child(even)`,
|
|
||||||
[]string{
|
|
||||||
`<li id="1">`,
|
|
||||||
`<li id="3">`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
`<ol><li id=1><li id=2><li id=3><li id=4></ol>`,
|
|
||||||
`li:nth-last-child(-n+2)`,
|
|
||||||
[]string{
|
|
||||||
`<li id="3">`,
|
|
||||||
`<li id="4">`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
`<ol><li id=1><li id=2><li id=3><li id=4></ol>`,
|
|
||||||
`li:nth-last-child(3n+1)`,
|
|
||||||
[]string{
|
|
||||||
`<li id="1">`,
|
|
||||||
`<li id="4">`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
`<p>some text <span id="1">and a span</span><span id="2"> and another</span></p>`,
|
|
||||||
`span:first-child`,
|
|
||||||
[]string{
|
|
||||||
`<span id="1">`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
`<span>a span</span> and some text`,
|
|
||||||
`span:last-child`,
|
|
||||||
[]string{
|
|
||||||
`<span>`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
`<address></address><p id=1><p id=2>`,
|
|
||||||
`p:nth-of-type(2)`,
|
|
||||||
[]string{
|
|
||||||
`<p id="2">`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
`<address></address><p id=1><p id=2></p><a>`,
|
|
||||||
`p:nth-last-of-type(2)`,
|
|
||||||
[]string{
|
|
||||||
`<p id="1">`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
`<address></address><p id=1><p id=2></p><a>`,
|
|
||||||
`p:last-of-type`,
|
|
||||||
[]string{
|
|
||||||
`<p id="2">`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
`<address></address><p id=1><p id=2></p><a>`,
|
|
||||||
`p:first-of-type`,
|
|
||||||
[]string{
|
|
||||||
`<p id="1">`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
`<div><p id="1"></p><a></a></div><div><p id="2"></p></div>`,
|
|
||||||
`p:only-child`,
|
|
||||||
[]string{
|
|
||||||
`<p id="2">`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
`<div><p id="1"></p><a></a></div><div><p id="2"></p><p id="3"></p></div>`,
|
|
||||||
`p:only-of-type`,
|
|
||||||
[]string{
|
|
||||||
`<p id="1">`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
`<p id="1"><!-- --><p id="2">Hello<p id="3"><span>`,
|
|
||||||
`:empty`,
|
|
||||||
[]string{
|
|
||||||
`<head>`,
|
|
||||||
`<p id="1">`,
|
|
||||||
`<span>`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
`<div><p id="1"><table><tr><td><p id="2"></table></div><p id="3">`,
|
|
||||||
`div p`,
|
|
||||||
[]string{
|
|
||||||
`<p id="1">`,
|
|
||||||
`<p id="2">`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
`<div><p id="1"><table><tr><td><p id="2"></table></div><p id="3">`,
|
|
||||||
`div table p`,
|
|
||||||
[]string{
|
|
||||||
`<p id="2">`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
`<div><p id="1"><div><p id="2"></div><table><tr><td><p id="3"></table></div>`,
|
|
||||||
`div > p`,
|
|
||||||
[]string{
|
|
||||||
`<p id="1">`,
|
|
||||||
`<p id="2">`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
`<p id="1"><p id="2"></p><address></address><p id="3">`,
|
|
||||||
`p ~ p`,
|
|
||||||
[]string{
|
|
||||||
`<p id="2">`,
|
|
||||||
`<p id="3">`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
`<p id="1"></p>
|
|
||||||
<!--comment-->
|
|
||||||
<p id="2"></p><address></address><p id="3">`,
|
|
||||||
`p + p`,
|
|
||||||
[]string{
|
|
||||||
`<p id="2">`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
`<ul><li></li><li></li></ul><p>`,
|
|
||||||
`li, p`,
|
|
||||||
[]string{
|
|
||||||
"<li>",
|
|
||||||
"<li>",
|
|
||||||
"<p>",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
`<p id="1"><p id="2"></p><address></address><p id="3">`,
|
|
||||||
`p +/*This is a comment*/ p`,
|
|
||||||
[]string{
|
|
||||||
`<p id="2">`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
`<p>Text block that <span>wraps inner text</span> and continues</p>`,
|
|
||||||
`p:contains("that wraps")`,
|
|
||||||
[]string{
|
|
||||||
`<p>`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
`<p>Text block that <span>wraps inner text</span> and continues</p>`,
|
|
||||||
`p:containsOwn("that wraps")`,
|
|
||||||
[]string{},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
`<p>Text block that <span>wraps inner text</span> and continues</p>`,
|
|
||||||
`:containsOwn("inner")`,
|
|
||||||
[]string{
|
|
||||||
`<span>`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
`<p>Text block that <span>wraps inner text</span> and continues</p>`,
|
|
||||||
`p:containsOwn("block")`,
|
|
||||||
[]string{
|
|
||||||
`<p>`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
`<div id="d1"><p id="p1"><span>text content</span></p></div><div id="d2"/>`,
|
|
||||||
`div:has(#p1)`,
|
|
||||||
[]string{
|
|
||||||
`<div id="d1">`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
`<div id="d1"><p id="p1"><span>contents 1</span></p></div>
|
|
||||||
<div id="d2"><p>contents <em>2</em></p></div>`,
|
|
||||||
`div:has(:containsOwn("2"))`,
|
|
||||||
[]string{
|
|
||||||
`<div id="d2">`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
`<body><div id="d1"><p id="p1"><span>contents 1</span></p></div>
|
|
||||||
<div id="d2"><p id="p2">contents <em>2</em></p></div></body>`,
|
|
||||||
`body :has(:containsOwn("2"))`,
|
|
||||||
[]string{
|
|
||||||
`<div id="d2">`,
|
|
||||||
`<p id="p2">`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
`<body><div id="d1"><p id="p1"><span>contents 1</span></p></div>
|
|
||||||
<div id="d2"><p id="p2">contents <em>2</em></p></div></body>`,
|
|
||||||
`body :haschild(:containsOwn("2"))`,
|
|
||||||
[]string{
|
|
||||||
`<p id="p2">`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
`<p id="p1">0123456789</p><p id="p2">abcdef</p><p id="p3">0123ABCD</p>`,
|
|
||||||
`p:matches([\d])`,
|
|
||||||
[]string{
|
|
||||||
`<p id="p1">`,
|
|
||||||
`<p id="p3">`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
`<p id="p1">0123456789</p><p id="p2">abcdef</p><p id="p3">0123ABCD</p>`,
|
|
||||||
`p:matches([a-z])`,
|
|
||||||
[]string{
|
|
||||||
`<p id="p2">`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
`<p id="p1">0123456789</p><p id="p2">abcdef</p><p id="p3">0123ABCD</p>`,
|
|
||||||
`p:matches([a-zA-Z])`,
|
|
||||||
[]string{
|
|
||||||
`<p id="p2">`,
|
|
||||||
`<p id="p3">`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
`<p id="p1">0123456789</p><p id="p2">abcdef</p><p id="p3">0123ABCD</p>`,
|
|
||||||
`p:matches([^\d])`,
|
|
||||||
[]string{
|
|
||||||
`<p id="p2">`,
|
|
||||||
`<p id="p3">`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
`<p id="p1">0123456789</p><p id="p2">abcdef</p><p id="p3">0123ABCD</p>`,
|
|
||||||
`p:matches(^(0|a))`,
|
|
||||||
[]string{
|
|
||||||
`<p id="p1">`,
|
|
||||||
`<p id="p2">`,
|
|
||||||
`<p id="p3">`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
`<p id="p1">0123456789</p><p id="p2">abcdef</p><p id="p3">0123ABCD</p>`,
|
|
||||||
`p:matches(^\d+$)`,
|
|
||||||
[]string{
|
|
||||||
`<p id="p1">`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
`<p id="p1">0123456789</p><p id="p2">abcdef</p><p id="p3">0123ABCD</p>`,
|
|
||||||
`p:not(:matches(^\d+$))`,
|
|
||||||
[]string{
|
|
||||||
`<p id="p2">`,
|
|
||||||
`<p id="p3">`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
`<div><p id="p1">01234<em>567</em>89</p><div>`,
|
|
||||||
`div :matchesOwn(^\d+$)`,
|
|
||||||
[]string{
|
|
||||||
`<p id="p1">`,
|
|
||||||
`<em>`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
`<ul>
|
|
||||||
<li><a id="a1" href="http://www.google.com/finance"/>
|
|
||||||
<li><a id="a2" href="http://finance.yahoo.com/"/>
|
|
||||||
<li><a id="a2" href="http://finance.untrusted.com/"/>
|
|
||||||
<li><a id="a3" href="https://www.google.com/news"/>
|
|
||||||
<li><a id="a4" href="http://news.yahoo.com"/>
|
|
||||||
</ul>`,
|
|
||||||
`[href#=(fina)]:not([href#=(\/\/[^\/]+untrusted)])`,
|
|
||||||
[]string{
|
|
||||||
`<a id="a1" href="http://www.google.com/finance">`,
|
|
||||||
`<a id="a2" href="http://finance.yahoo.com/">`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
`<ul>
|
|
||||||
<li><a id="a1" href="http://www.google.com/finance"/>
|
|
||||||
<li><a id="a2" href="http://finance.yahoo.com/"/>
|
|
||||||
<li><a id="a3" href="https://www.google.com/news"/>
|
|
||||||
<li><a id="a4" href="http://news.yahoo.com"/>
|
|
||||||
</ul>`,
|
|
||||||
`[href#=(^https:\/\/[^\/]*\/?news)]`,
|
|
||||||
[]string{
|
|
||||||
`<a id="a3" href="https://www.google.com/news">`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
`<form>
|
|
||||||
<label>Username <input type="text" name="username" /></label>
|
|
||||||
<label>Password <input type="password" name="password" /></label>
|
|
||||||
<label>Country
|
|
||||||
<select name="country">
|
|
||||||
<option value="ca">Canada</option>
|
|
||||||
<option value="us">United States</option>
|
|
||||||
</select>
|
|
||||||
</label>
|
|
||||||
<label>Bio <textarea name="bio"></textarea></label>
|
|
||||||
<button>Sign up</button>
|
|
||||||
</form>`,
|
|
||||||
`:input`,
|
|
||||||
[]string{
|
|
||||||
`<input type="text" name="username">`,
|
|
||||||
`<input type="password" name="password">`,
|
|
||||||
`<select name="country">`,
|
|
||||||
`<textarea name="bio">`,
|
|
||||||
`<button>`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSelectors(t *testing.T) {
|
|
||||||
for _, test := range selectorTests {
|
|
||||||
s, err := Compile(test.selector)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("error compiling %q: %s", test.selector, err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
doc, err := html.Parse(strings.NewReader(test.HTML))
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("error parsing %q: %s", test.HTML, err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
matches := s.MatchAll(doc)
|
|
||||||
if len(matches) != len(test.results) {
|
|
||||||
t.Errorf("wanted %d elements, got %d instead", len(test.results), len(matches))
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
for i, m := range matches {
|
|
||||||
got := nodeString(m)
|
|
||||||
if got != test.results[i] {
|
|
||||||
t.Errorf("wanted %s, got %s instead", test.results[i], got)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
firstMatch := s.MatchFirst(doc)
|
|
||||||
if len(test.results) == 0 {
|
|
||||||
if firstMatch != nil {
|
|
||||||
t.Errorf("MatchFirst: want nil, got %s", nodeString(firstMatch))
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
got := nodeString(firstMatch)
|
|
||||||
if got != test.results[0] {
|
|
||||||
t.Errorf("MatchFirst: want %s, got %s", test.results[0], got)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
64
Godeps/_workspace/src/github.com/coreos/pkg/flagutil/env_test.go
generated
vendored
64
Godeps/_workspace/src/github.com/coreos/pkg/flagutil/env_test.go
generated
vendored
|
@ -1,64 +0,0 @@
|
||||||
package flagutil
|
|
||||||
|
|
||||||
import (
|
|
||||||
"flag"
|
|
||||||
"os"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestSetFlagsFromEnv(t *testing.T) {
|
|
||||||
fs := flag.NewFlagSet("testing", flag.ExitOnError)
|
|
||||||
fs.String("a", "", "")
|
|
||||||
fs.String("b", "", "")
|
|
||||||
fs.String("c", "", "")
|
|
||||||
fs.Parse([]string{})
|
|
||||||
|
|
||||||
os.Clearenv()
|
|
||||||
// flags should be settable using env vars
|
|
||||||
os.Setenv("MYPROJ_A", "foo")
|
|
||||||
// and command-line flags
|
|
||||||
if err := fs.Set("b", "bar"); err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
// command-line flags take precedence over env vars
|
|
||||||
os.Setenv("MYPROJ_C", "woof")
|
|
||||||
if err := fs.Set("c", "quack"); err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// first verify that flags are as expected before reading the env
|
|
||||||
for f, want := range map[string]string{
|
|
||||||
"a": "",
|
|
||||||
"b": "bar",
|
|
||||||
"c": "quack",
|
|
||||||
} {
|
|
||||||
if got := fs.Lookup(f).Value.String(); got != want {
|
|
||||||
t.Fatalf("flag %q=%q, want %q", f, got, want)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// now read the env and verify flags were updated as expected
|
|
||||||
err := SetFlagsFromEnv(fs, "MYPROJ")
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("err=%v, want nil", err)
|
|
||||||
}
|
|
||||||
for f, want := range map[string]string{
|
|
||||||
"a": "foo",
|
|
||||||
"b": "bar",
|
|
||||||
"c": "quack",
|
|
||||||
} {
|
|
||||||
if got := fs.Lookup(f).Value.String(); got != want {
|
|
||||||
t.Errorf("flag %q=%q, want %q", f, got, want)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSetFlagsFromEnvBad(t *testing.T) {
|
|
||||||
// now verify that an error is propagated
|
|
||||||
fs := flag.NewFlagSet("testing", flag.ExitOnError)
|
|
||||||
fs.Int("x", 0, "")
|
|
||||||
os.Setenv("MYPROJ_X", "not_a_number")
|
|
||||||
if err := SetFlagsFromEnv(fs, "MYPROJ"); err == nil {
|
|
||||||
t.Errorf("err=nil, want != nil")
|
|
||||||
}
|
|
||||||
}
|
|
57
Godeps/_workspace/src/github.com/coreos/pkg/flagutil/types_test.go
generated
vendored
57
Godeps/_workspace/src/github.com/coreos/pkg/flagutil/types_test.go
generated
vendored
|
@ -1,57 +0,0 @@
|
||||||
package flagutil
|
|
||||||
|
|
||||||
import (
|
|
||||||
"reflect"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestIPv4FlagSetInvalidArgument(t *testing.T) {
|
|
||||||
tests := []string{
|
|
||||||
"",
|
|
||||||
"foo",
|
|
||||||
"::",
|
|
||||||
"127.0.0.1:4328",
|
|
||||||
}
|
|
||||||
|
|
||||||
for i, tt := range tests {
|
|
||||||
var f IPv4Flag
|
|
||||||
if err := f.Set(tt); err == nil {
|
|
||||||
t.Errorf("case %d: expected non-nil error", i)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestIPv4FlagSetValidArgument(t *testing.T) {
|
|
||||||
tests := []string{
|
|
||||||
"127.0.0.1",
|
|
||||||
"0.0.0.0",
|
|
||||||
}
|
|
||||||
|
|
||||||
for i, tt := range tests {
|
|
||||||
var f IPv4Flag
|
|
||||||
if err := f.Set(tt); err != nil {
|
|
||||||
t.Errorf("case %d: err=%v", i, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestStringSliceFlag(t *testing.T) {
|
|
||||||
tests := []struct {
|
|
||||||
input string
|
|
||||||
want []string
|
|
||||||
}{
|
|
||||||
{input: "", want: []string{""}},
|
|
||||||
{input: "foo", want: []string{"foo"}},
|
|
||||||
{input: "foo,bar", want: []string{"foo", "bar"}},
|
|
||||||
}
|
|
||||||
|
|
||||||
for i, tt := range tests {
|
|
||||||
var f StringSliceFlag
|
|
||||||
if err := f.Set(tt.input); err != nil {
|
|
||||||
t.Errorf("case %d: err=%v", i, err)
|
|
||||||
}
|
|
||||||
if !reflect.DeepEqual(tt.want, []string(f)) {
|
|
||||||
t.Errorf("case %d: want=%v got=%v", i, tt.want, f)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
198
Godeps/_workspace/src/github.com/coreos/pkg/health/health_test.go
generated
vendored
198
Godeps/_workspace/src/github.com/coreos/pkg/health/health_test.go
generated
vendored
|
@ -1,198 +0,0 @@
|
||||||
package health
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"errors"
|
|
||||||
"net/http"
|
|
||||||
"net/http/httptest"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/coreos/pkg/httputil"
|
|
||||||
)
|
|
||||||
|
|
||||||
type boolChecker bool
|
|
||||||
|
|
||||||
func (b boolChecker) Healthy() error {
|
|
||||||
if b {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return errors.New("Unhealthy")
|
|
||||||
}
|
|
||||||
|
|
||||||
func errString(err error) string {
|
|
||||||
if err == nil {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
return err.Error()
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCheck(t *testing.T) {
|
|
||||||
for i, test := range []struct {
|
|
||||||
checks []Checkable
|
|
||||||
expected string
|
|
||||||
}{
|
|
||||||
{[]Checkable{}, ""},
|
|
||||||
|
|
||||||
{[]Checkable{boolChecker(true)}, ""},
|
|
||||||
|
|
||||||
{[]Checkable{boolChecker(true), boolChecker(true)}, ""},
|
|
||||||
|
|
||||||
{[]Checkable{boolChecker(true), boolChecker(false)}, "Unhealthy"},
|
|
||||||
|
|
||||||
{[]Checkable{boolChecker(true), boolChecker(false), boolChecker(false)}, "multiple health check failure: [Unhealthy Unhealthy]"},
|
|
||||||
} {
|
|
||||||
err := Check(test.checks)
|
|
||||||
|
|
||||||
if errString(err) != test.expected {
|
|
||||||
t.Errorf("case %d: want %v, got %v", i, test.expected, errString(err))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestHandlerFunc(t *testing.T) {
|
|
||||||
for i, test := range []struct {
|
|
||||||
checker Checker
|
|
||||||
method string
|
|
||||||
expectedStatus string
|
|
||||||
expectedCode int
|
|
||||||
expectedMessage string
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
Checker{
|
|
||||||
Checks: []Checkable{
|
|
||||||
boolChecker(true),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"GET",
|
|
||||||
"ok",
|
|
||||||
http.StatusOK,
|
|
||||||
"",
|
|
||||||
},
|
|
||||||
|
|
||||||
// Wrong method.
|
|
||||||
{
|
|
||||||
Checker{
|
|
||||||
Checks: []Checkable{
|
|
||||||
boolChecker(true),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"POST",
|
|
||||||
"",
|
|
||||||
http.StatusMethodNotAllowed,
|
|
||||||
"GET only acceptable method",
|
|
||||||
},
|
|
||||||
|
|
||||||
// Health check fails.
|
|
||||||
{
|
|
||||||
Checker{
|
|
||||||
Checks: []Checkable{
|
|
||||||
boolChecker(false),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"GET",
|
|
||||||
"error",
|
|
||||||
http.StatusInternalServerError,
|
|
||||||
"Unhealthy",
|
|
||||||
},
|
|
||||||
|
|
||||||
// Health check fails, with overridden ErrorHandler.
|
|
||||||
{
|
|
||||||
Checker{
|
|
||||||
Checks: []Checkable{
|
|
||||||
boolChecker(false),
|
|
||||||
},
|
|
||||||
UnhealthyHandler: func(w http.ResponseWriter, r *http.Request, err error) {
|
|
||||||
httputil.WriteJSONResponse(w,
|
|
||||||
http.StatusInternalServerError, StatusResponse{
|
|
||||||
Status: "error",
|
|
||||||
Details: &StatusResponseDetails{
|
|
||||||
Code: http.StatusInternalServerError,
|
|
||||||
Message: "Override!",
|
|
||||||
},
|
|
||||||
})
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"GET",
|
|
||||||
"error",
|
|
||||||
http.StatusInternalServerError,
|
|
||||||
"Override!",
|
|
||||||
},
|
|
||||||
|
|
||||||
// Health check succeeds, with overridden SuccessHandler.
|
|
||||||
{
|
|
||||||
Checker{
|
|
||||||
Checks: []Checkable{
|
|
||||||
boolChecker(true),
|
|
||||||
},
|
|
||||||
HealthyHandler: func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
httputil.WriteJSONResponse(w,
|
|
||||||
http.StatusOK, StatusResponse{
|
|
||||||
Status: "okey-dokey",
|
|
||||||
})
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"GET",
|
|
||||||
"okey-dokey",
|
|
||||||
http.StatusOK,
|
|
||||||
"",
|
|
||||||
},
|
|
||||||
} {
|
|
||||||
w := httptest.NewRecorder()
|
|
||||||
r := &http.Request{}
|
|
||||||
r.Method = test.method
|
|
||||||
test.checker.ServeHTTP(w, r)
|
|
||||||
if w.Code != test.expectedCode {
|
|
||||||
t.Errorf("case %d: w.code == %v, want %v", i, w.Code, test.expectedCode)
|
|
||||||
}
|
|
||||||
|
|
||||||
if test.expectedStatus == "" {
|
|
||||||
// This is to handle the wrong-method case, when the
|
|
||||||
// body of the response is empty.
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
statusMap := make(map[string]interface{})
|
|
||||||
err := json.Unmarshal(w.Body.Bytes(), &statusMap)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("case %d: failed to Unmarshal response body: %v", i, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
status, ok := statusMap["status"].(string)
|
|
||||||
if !ok {
|
|
||||||
t.Errorf("case %d: status not present or not a string in json: %q", i, w.Body.Bytes())
|
|
||||||
}
|
|
||||||
if status != test.expectedStatus {
|
|
||||||
t.Errorf("case %d: status == %v, want %v", i, status, test.expectedStatus)
|
|
||||||
}
|
|
||||||
|
|
||||||
detailMap, ok := statusMap["details"].(map[string]interface{})
|
|
||||||
if test.expectedMessage != "" {
|
|
||||||
if !ok {
|
|
||||||
t.Fatalf("case %d: could not find/unmarshal detailMap", i)
|
|
||||||
}
|
|
||||||
message, ok := detailMap["message"].(string)
|
|
||||||
if !ok {
|
|
||||||
t.Fatalf("case %d: message not present or not a string in json: %q",
|
|
||||||
i, w.Body.Bytes())
|
|
||||||
}
|
|
||||||
if message != test.expectedMessage {
|
|
||||||
t.Errorf("case %d: message == %v, want %v", i, message, test.expectedMessage)
|
|
||||||
}
|
|
||||||
|
|
||||||
code, ok := detailMap["code"].(float64)
|
|
||||||
if !ok {
|
|
||||||
t.Fatalf("case %d: code not present or not an int in json: %q",
|
|
||||||
i, w.Body.Bytes())
|
|
||||||
}
|
|
||||||
if int(code) != test.expectedCode {
|
|
||||||
t.Errorf("case %d: code == %v, want %v", i, code, test.expectedCode)
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
if ok {
|
|
||||||
t.Errorf("case %d: unwanted detailMap present: %q", i, detailMap)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
56
Godeps/_workspace/src/github.com/coreos/pkg/httputil/json_test.go
generated
vendored
56
Godeps/_workspace/src/github.com/coreos/pkg/httputil/json_test.go
generated
vendored
|
@ -1,56 +0,0 @@
|
||||||
package httputil
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net/http/httptest"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestWriteJSONResponse(t *testing.T) {
|
|
||||||
for i, test := range []struct {
|
|
||||||
code int
|
|
||||||
resp interface{}
|
|
||||||
expectedJSON string
|
|
||||||
expectErr bool
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
200,
|
|
||||||
struct {
|
|
||||||
A string
|
|
||||||
B string
|
|
||||||
}{A: "foo", B: "bar"},
|
|
||||||
`{"A":"foo","B":"bar"}`,
|
|
||||||
false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
500,
|
|
||||||
// Something that json.Marshal cannot serialize.
|
|
||||||
make(chan int),
|
|
||||||
"",
|
|
||||||
true,
|
|
||||||
},
|
|
||||||
} {
|
|
||||||
w := httptest.NewRecorder()
|
|
||||||
err := WriteJSONResponse(w, test.code, test.resp)
|
|
||||||
|
|
||||||
if w.Code != test.code {
|
|
||||||
t.Errorf("case %d: w.code == %v, want %v", i, w.Code, test.code)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (err != nil) != test.expectErr {
|
|
||||||
t.Errorf("case %d: (err != nil) == %v, want %v. err: %v", i, err != nil, test.expectErr, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if string(w.Body.Bytes()) != test.expectedJSON {
|
|
||||||
t.Errorf("case %d: w.Body.Bytes()) == %q, want %q", i,
|
|
||||||
string(w.Body.Bytes()), test.expectedJSON)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !test.expectErr {
|
|
||||||
contentType := w.Header()["Content-Type"][0]
|
|
||||||
if contentType != JSONContentType {
|
|
||||||
t.Errorf("case %d: contentType == %v, want %v", i, contentType, JSONContentType)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
52
Godeps/_workspace/src/github.com/coreos/pkg/timeutil/backoff_test.go
generated
vendored
52
Godeps/_workspace/src/github.com/coreos/pkg/timeutil/backoff_test.go
generated
vendored
|
@ -1,52 +0,0 @@
|
||||||
package timeutil
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestExpBackoff(t *testing.T) {
|
|
||||||
tests := []struct {
|
|
||||||
prev time.Duration
|
|
||||||
max time.Duration
|
|
||||||
want time.Duration
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
prev: time.Duration(0),
|
|
||||||
max: time.Minute,
|
|
||||||
want: time.Second,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
prev: time.Second,
|
|
||||||
max: time.Minute,
|
|
||||||
want: 2 * time.Second,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
prev: 16 * time.Second,
|
|
||||||
max: time.Minute,
|
|
||||||
want: 32 * time.Second,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
prev: 32 * time.Second,
|
|
||||||
max: time.Minute,
|
|
||||||
want: time.Minute,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
prev: time.Minute,
|
|
||||||
max: time.Minute,
|
|
||||||
want: time.Minute,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
prev: 2 * time.Minute,
|
|
||||||
max: time.Minute,
|
|
||||||
want: time.Minute,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for i, tt := range tests {
|
|
||||||
got := ExpBackoff(tt.prev, tt.max)
|
|
||||||
if tt.want != got {
|
|
||||||
t.Errorf("case %d: want=%v got=%v", i, tt.want, got)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
2340
Godeps/_workspace/src/github.com/go-gorp/gorp/gorp_test.go
generated
vendored
2340
Godeps/_workspace/src/github.com/go-gorp/gorp/gorp_test.go
generated
vendored
File diff suppressed because it is too large
Load diff
73
Godeps/_workspace/src/github.com/gorilla/handlers/canonical_test.go
generated
vendored
73
Godeps/_workspace/src/github.com/gorilla/handlers/canonical_test.go
generated
vendored
|
@ -1,73 +0,0 @@
|
||||||
package handlers
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net/http"
|
|
||||||
"net/http/httptest"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestCleanHost(t *testing.T) {
|
|
||||||
tests := []struct {
|
|
||||||
in, want string
|
|
||||||
}{
|
|
||||||
{"www.google.com", "www.google.com"},
|
|
||||||
{"www.google.com foo", "www.google.com"},
|
|
||||||
{"www.google.com/foo", "www.google.com"},
|
|
||||||
{" first character is a space", ""},
|
|
||||||
}
|
|
||||||
for _, tt := range tests {
|
|
||||||
got := cleanHost(tt.in)
|
|
||||||
if tt.want != got {
|
|
||||||
t.Errorf("cleanHost(%q) = %q, want %q", tt.in, got, tt.want)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCanonicalHost(t *testing.T) {
|
|
||||||
gorilla := "http://www.gorillatoolkit.org"
|
|
||||||
|
|
||||||
rr := httptest.NewRecorder()
|
|
||||||
r := newRequest("GET", "http://www.example.com/")
|
|
||||||
|
|
||||||
testHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {})
|
|
||||||
|
|
||||||
// Test a re-direct: should return a 302 Found.
|
|
||||||
CanonicalHost(gorilla, http.StatusFound)(testHandler).ServeHTTP(rr, r)
|
|
||||||
|
|
||||||
if rr.Code != http.StatusFound {
|
|
||||||
t.Fatalf("bad status: got %v want %v", rr.Code, http.StatusFound)
|
|
||||||
}
|
|
||||||
|
|
||||||
if rr.Header().Get("Location") != gorilla+r.URL.Path {
|
|
||||||
t.Fatalf("bad re-direct: got %q want %q", rr.Header().Get("Location"), gorilla+r.URL.Path)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestBadDomain(t *testing.T) {
|
|
||||||
rr := httptest.NewRecorder()
|
|
||||||
r := newRequest("GET", "http://www.example.com/")
|
|
||||||
|
|
||||||
testHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {})
|
|
||||||
|
|
||||||
// Test a bad domain - should return 200 OK.
|
|
||||||
CanonicalHost("%", http.StatusFound)(testHandler).ServeHTTP(rr, r)
|
|
||||||
|
|
||||||
if rr.Code != http.StatusOK {
|
|
||||||
t.Fatalf("bad status: got %v want %v", rr.Code, http.StatusOK)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestEmptyHost(t *testing.T) {
|
|
||||||
rr := httptest.NewRecorder()
|
|
||||||
r := newRequest("GET", "http://www.example.com/")
|
|
||||||
|
|
||||||
testHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {})
|
|
||||||
|
|
||||||
// Test a domain that returns an empty url.Host from url.Parse.
|
|
||||||
CanonicalHost("hello.com", http.StatusFound)(testHandler).ServeHTTP(rr, r)
|
|
||||||
|
|
||||||
if rr.Code != http.StatusOK {
|
|
||||||
t.Fatalf("bad status: got %v want %v", rr.Code, http.StatusOK)
|
|
||||||
}
|
|
||||||
}
|
|
65
Godeps/_workspace/src/github.com/gorilla/handlers/compress_test.go
generated
vendored
65
Godeps/_workspace/src/github.com/gorilla/handlers/compress_test.go
generated
vendored
|
@ -1,65 +0,0 @@
|
||||||
// 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 handlers
|
|
||||||
|
|
||||||
import (
|
|
||||||
"io"
|
|
||||||
"net/http"
|
|
||||||
"net/http/httptest"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func compressedRequest(w *httptest.ResponseRecorder, compression string) {
|
|
||||||
CompressHandler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
for i := 0; i < 1024; i++ {
|
|
||||||
io.WriteString(w, "Gorilla!\n")
|
|
||||||
}
|
|
||||||
})).ServeHTTP(w, &http.Request{
|
|
||||||
Method: "GET",
|
|
||||||
Header: http.Header{
|
|
||||||
"Accept-Encoding": []string{compression},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCompressHandlerGzip(t *testing.T) {
|
|
||||||
w := httptest.NewRecorder()
|
|
||||||
compressedRequest(w, "gzip")
|
|
||||||
if w.HeaderMap.Get("Content-Encoding") != "gzip" {
|
|
||||||
t.Fatalf("wrong content encoding, got %d want %d", w.HeaderMap.Get("Content-Encoding"), "gzip")
|
|
||||||
}
|
|
||||||
if w.HeaderMap.Get("Content-Type") != "text/plain; charset=utf-8" {
|
|
||||||
t.Fatalf("wrong content type, got %s want %s", w.HeaderMap.Get("Content-Type"), "text/plain; charset=utf-8")
|
|
||||||
}
|
|
||||||
if w.Body.Len() != 72 {
|
|
||||||
t.Fatalf("wrong len, got %d want %d", w.Body.Len(), 72)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCompressHandlerDeflate(t *testing.T) {
|
|
||||||
w := httptest.NewRecorder()
|
|
||||||
compressedRequest(w, "deflate")
|
|
||||||
if w.HeaderMap.Get("Content-Encoding") != "deflate" {
|
|
||||||
t.Fatalf("wrong content encoding, got %d want %d", w.HeaderMap.Get("Content-Encoding"), "deflate")
|
|
||||||
}
|
|
||||||
if w.HeaderMap.Get("Content-Type") != "text/plain; charset=utf-8" {
|
|
||||||
t.Fatalf("wrong content type, got %s want %s", w.HeaderMap.Get("Content-Type"), "text/plain; charset=utf-8")
|
|
||||||
}
|
|
||||||
if w.Body.Len() != 54 {
|
|
||||||
t.Fatalf("wrong len, got %d want %d", w.Body.Len(), 54)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCompressHandlerGzipDeflate(t *testing.T) {
|
|
||||||
w := httptest.NewRecorder()
|
|
||||||
compressedRequest(w, "gzip, deflate ")
|
|
||||||
if w.HeaderMap.Get("Content-Encoding") != "gzip" {
|
|
||||||
t.Fatalf("wrong content encoding, got %s want %s", w.HeaderMap.Get("Content-Encoding"), "gzip")
|
|
||||||
}
|
|
||||||
if w.HeaderMap.Get("Content-Type") != "text/plain; charset=utf-8" {
|
|
||||||
t.Fatalf("wrong content type, got %s want %s", w.HeaderMap.Get("Content-Type"), "text/plain; charset=utf-8")
|
|
||||||
}
|
|
||||||
}
|
|
305
Godeps/_workspace/src/github.com/gorilla/handlers/handlers_test.go
generated
vendored
305
Godeps/_workspace/src/github.com/gorilla/handlers/handlers_test.go
generated
vendored
|
@ -1,305 +0,0 @@
|
||||||
// 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 handlers
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"net"
|
|
||||||
"net/http"
|
|
||||||
"net/http/httptest"
|
|
||||||
"net/url"
|
|
||||||
"strings"
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
ok = "ok\n"
|
|
||||||
notAllowed = "Method not allowed\n"
|
|
||||||
)
|
|
||||||
|
|
||||||
var okHandler = http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
|
||||||
w.Write([]byte(ok))
|
|
||||||
})
|
|
||||||
|
|
||||||
func newRequest(method, url string) *http.Request {
|
|
||||||
req, err := http.NewRequest(method, url, nil)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
return req
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestMethodHandler(t *testing.T) {
|
|
||||||
tests := []struct {
|
|
||||||
req *http.Request
|
|
||||||
handler http.Handler
|
|
||||||
code int
|
|
||||||
allow string // Contents of the Allow header
|
|
||||||
body string
|
|
||||||
}{
|
|
||||||
// No handlers
|
|
||||||
{newRequest("GET", "/foo"), MethodHandler{}, http.StatusMethodNotAllowed, "", notAllowed},
|
|
||||||
{newRequest("OPTIONS", "/foo"), MethodHandler{}, http.StatusOK, "", ""},
|
|
||||||
|
|
||||||
// A single handler
|
|
||||||
{newRequest("GET", "/foo"), MethodHandler{"GET": okHandler}, http.StatusOK, "", ok},
|
|
||||||
{newRequest("POST", "/foo"), MethodHandler{"GET": okHandler}, http.StatusMethodNotAllowed, "GET", notAllowed},
|
|
||||||
|
|
||||||
// Multiple handlers
|
|
||||||
{newRequest("GET", "/foo"), MethodHandler{"GET": okHandler, "POST": okHandler}, http.StatusOK, "", ok},
|
|
||||||
{newRequest("POST", "/foo"), MethodHandler{"GET": okHandler, "POST": okHandler}, http.StatusOK, "", ok},
|
|
||||||
{newRequest("DELETE", "/foo"), MethodHandler{"GET": okHandler, "POST": okHandler}, http.StatusMethodNotAllowed, "GET, POST", notAllowed},
|
|
||||||
{newRequest("OPTIONS", "/foo"), MethodHandler{"GET": okHandler, "POST": okHandler}, http.StatusOK, "GET, POST", ""},
|
|
||||||
|
|
||||||
// Override OPTIONS
|
|
||||||
{newRequest("OPTIONS", "/foo"), MethodHandler{"OPTIONS": okHandler}, http.StatusOK, "", ok},
|
|
||||||
}
|
|
||||||
|
|
||||||
for i, test := range tests {
|
|
||||||
rec := httptest.NewRecorder()
|
|
||||||
test.handler.ServeHTTP(rec, test.req)
|
|
||||||
if rec.Code != test.code {
|
|
||||||
t.Fatalf("%d: wrong code, got %d want %d", i, rec.Code, test.code)
|
|
||||||
}
|
|
||||||
if allow := rec.HeaderMap.Get("Allow"); allow != test.allow {
|
|
||||||
t.Fatalf("%d: wrong Allow, got %s want %s", i, allow, test.allow)
|
|
||||||
}
|
|
||||||
if body := rec.Body.String(); body != test.body {
|
|
||||||
t.Fatalf("%d: wrong body, got %q want %q", i, body, test.body)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestWriteLog(t *testing.T) {
|
|
||||||
loc, err := time.LoadLocation("Europe/Warsaw")
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
ts := time.Date(1983, 05, 26, 3, 30, 45, 0, loc)
|
|
||||||
|
|
||||||
// A typical request with an OK response
|
|
||||||
req := newRequest("GET", "http://example.com")
|
|
||||||
req.RemoteAddr = "192.168.100.5"
|
|
||||||
|
|
||||||
buf := new(bytes.Buffer)
|
|
||||||
writeLog(buf, req, *req.URL, ts, http.StatusOK, 100)
|
|
||||||
log := buf.String()
|
|
||||||
|
|
||||||
expected := "192.168.100.5 - - [26/May/1983:03:30:45 +0200] \"GET / HTTP/1.1\" 200 100\n"
|
|
||||||
if log != expected {
|
|
||||||
t.Fatalf("wrong log, got %q want %q", log, expected)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Request with an unauthorized user
|
|
||||||
req = newRequest("GET", "http://example.com")
|
|
||||||
req.RemoteAddr = "192.168.100.5"
|
|
||||||
req.URL.User = url.User("kamil")
|
|
||||||
|
|
||||||
buf.Reset()
|
|
||||||
writeLog(buf, req, *req.URL, ts, http.StatusUnauthorized, 500)
|
|
||||||
log = buf.String()
|
|
||||||
|
|
||||||
expected = "192.168.100.5 - kamil [26/May/1983:03:30:45 +0200] \"GET / HTTP/1.1\" 401 500\n"
|
|
||||||
if log != expected {
|
|
||||||
t.Fatalf("wrong log, got %q want %q", log, expected)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Request with url encoded parameters
|
|
||||||
req = newRequest("GET", "http://example.com/test?abc=hello%20world&a=b%3F")
|
|
||||||
req.RemoteAddr = "192.168.100.5"
|
|
||||||
|
|
||||||
buf.Reset()
|
|
||||||
writeLog(buf, req, *req.URL, ts, http.StatusOK, 100)
|
|
||||||
log = buf.String()
|
|
||||||
|
|
||||||
expected = "192.168.100.5 - - [26/May/1983:03:30:45 +0200] \"GET /test?abc=hello%20world&a=b%3F HTTP/1.1\" 200 100\n"
|
|
||||||
if log != expected {
|
|
||||||
t.Fatalf("wrong log, got %q want %q", log, expected)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestWriteCombinedLog(t *testing.T) {
|
|
||||||
loc, err := time.LoadLocation("Europe/Warsaw")
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
ts := time.Date(1983, 05, 26, 3, 30, 45, 0, loc)
|
|
||||||
|
|
||||||
// A typical request with an OK response
|
|
||||||
req := newRequest("GET", "http://example.com")
|
|
||||||
req.RemoteAddr = "192.168.100.5"
|
|
||||||
req.Header.Set("Referer", "http://example.com")
|
|
||||||
req.Header.Set(
|
|
||||||
"User-Agent",
|
|
||||||
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/537.33 "+
|
|
||||||
"(KHTML, like Gecko) Chrome/27.0.1430.0 Safari/537.33",
|
|
||||||
)
|
|
||||||
|
|
||||||
buf := new(bytes.Buffer)
|
|
||||||
writeCombinedLog(buf, req, *req.URL, ts, http.StatusOK, 100)
|
|
||||||
log := buf.String()
|
|
||||||
|
|
||||||
expected := "192.168.100.5 - - [26/May/1983:03:30:45 +0200] \"GET / HTTP/1.1\" 200 100 \"http://example.com\" " +
|
|
||||||
"\"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) " +
|
|
||||||
"AppleWebKit/537.33 (KHTML, like Gecko) Chrome/27.0.1430.0 Safari/537.33\"\n"
|
|
||||||
if log != expected {
|
|
||||||
t.Fatalf("wrong log, got %q want %q", log, expected)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Request with an unauthorized user
|
|
||||||
req.URL.User = url.User("kamil")
|
|
||||||
|
|
||||||
buf.Reset()
|
|
||||||
writeCombinedLog(buf, req, *req.URL, ts, http.StatusUnauthorized, 500)
|
|
||||||
log = buf.String()
|
|
||||||
|
|
||||||
expected = "192.168.100.5 - kamil [26/May/1983:03:30:45 +0200] \"GET / HTTP/1.1\" 401 500 \"http://example.com\" " +
|
|
||||||
"\"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) " +
|
|
||||||
"AppleWebKit/537.33 (KHTML, like Gecko) Chrome/27.0.1430.0 Safari/537.33\"\n"
|
|
||||||
if log != expected {
|
|
||||||
t.Fatalf("wrong log, got %q want %q", log, expected)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test with remote ipv6 address
|
|
||||||
req.RemoteAddr = "::1"
|
|
||||||
|
|
||||||
buf.Reset()
|
|
||||||
writeCombinedLog(buf, req, *req.URL, ts, http.StatusOK, 100)
|
|
||||||
log = buf.String()
|
|
||||||
|
|
||||||
expected = "::1 - kamil [26/May/1983:03:30:45 +0200] \"GET / HTTP/1.1\" 200 100 \"http://example.com\" " +
|
|
||||||
"\"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) " +
|
|
||||||
"AppleWebKit/537.33 (KHTML, like Gecko) Chrome/27.0.1430.0 Safari/537.33\"\n"
|
|
||||||
if log != expected {
|
|
||||||
t.Fatalf("wrong log, got %q want %q", log, expected)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test remote ipv6 addr, with port
|
|
||||||
req.RemoteAddr = net.JoinHostPort("::1", "65000")
|
|
||||||
|
|
||||||
buf.Reset()
|
|
||||||
writeCombinedLog(buf, req, *req.URL, ts, http.StatusOK, 100)
|
|
||||||
log = buf.String()
|
|
||||||
|
|
||||||
expected = "::1 - kamil [26/May/1983:03:30:45 +0200] \"GET / HTTP/1.1\" 200 100 \"http://example.com\" " +
|
|
||||||
"\"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) " +
|
|
||||||
"AppleWebKit/537.33 (KHTML, like Gecko) Chrome/27.0.1430.0 Safari/537.33\"\n"
|
|
||||||
if log != expected {
|
|
||||||
t.Fatalf("wrong log, got %q want %q", log, expected)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestLogPathRewrites(t *testing.T) {
|
|
||||||
var buf bytes.Buffer
|
|
||||||
|
|
||||||
handler := http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
|
||||||
req.URL.Path = "/" // simulate http.StripPrefix and friends
|
|
||||||
w.WriteHeader(200)
|
|
||||||
})
|
|
||||||
logger := LoggingHandler(&buf, handler)
|
|
||||||
|
|
||||||
logger.ServeHTTP(httptest.NewRecorder(), newRequest("GET", "/subdir/asdf"))
|
|
||||||
|
|
||||||
if !strings.Contains(buf.String(), "GET /subdir/asdf HTTP") {
|
|
||||||
t.Fatalf("Got log %#v, wanted substring %#v", buf.String(), "GET /subdir/asdf HTTP")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkWriteLog(b *testing.B) {
|
|
||||||
loc, err := time.LoadLocation("Europe/Warsaw")
|
|
||||||
if err != nil {
|
|
||||||
b.Fatalf(err.Error())
|
|
||||||
}
|
|
||||||
ts := time.Date(1983, 05, 26, 3, 30, 45, 0, loc)
|
|
||||||
|
|
||||||
req := newRequest("GET", "http://example.com")
|
|
||||||
req.RemoteAddr = "192.168.100.5"
|
|
||||||
|
|
||||||
b.ResetTimer()
|
|
||||||
|
|
||||||
buf := &bytes.Buffer{}
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
buf.Reset()
|
|
||||||
writeLog(buf, req, *req.URL, ts, http.StatusUnauthorized, 500)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestContentTypeHandler(t *testing.T) {
|
|
||||||
tests := []struct {
|
|
||||||
Method string
|
|
||||||
AllowContentTypes []string
|
|
||||||
ContentType string
|
|
||||||
Code int
|
|
||||||
}{
|
|
||||||
{"POST", []string{"application/json"}, "application/json", http.StatusOK},
|
|
||||||
{"POST", []string{"application/json", "application/xml"}, "application/json", http.StatusOK},
|
|
||||||
{"POST", []string{"application/json"}, "application/json; charset=utf-8", http.StatusOK},
|
|
||||||
{"POST", []string{"application/json"}, "application/json+xxx", http.StatusUnsupportedMediaType},
|
|
||||||
{"POST", []string{"application/json"}, "text/plain", http.StatusUnsupportedMediaType},
|
|
||||||
{"GET", []string{"application/json"}, "", http.StatusOK},
|
|
||||||
{"GET", []string{}, "", http.StatusOK},
|
|
||||||
}
|
|
||||||
for _, test := range tests {
|
|
||||||
r, err := http.NewRequest(test.Method, "/", nil)
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
h := ContentTypeHandler(okHandler, test.AllowContentTypes...)
|
|
||||||
r.Header.Set("Content-Type", test.ContentType)
|
|
||||||
w := httptest.NewRecorder()
|
|
||||||
h.ServeHTTP(w, r)
|
|
||||||
if w.Code != test.Code {
|
|
||||||
t.Errorf("expected %d, got %d", test.Code, w.Code)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestHTTPMethodOverride(t *testing.T) {
|
|
||||||
var tests = []struct {
|
|
||||||
Method string
|
|
||||||
OverrideMethod string
|
|
||||||
ExpectedMethod string
|
|
||||||
}{
|
|
||||||
{"POST", "PUT", "PUT"},
|
|
||||||
{"POST", "PATCH", "PATCH"},
|
|
||||||
{"POST", "DELETE", "DELETE"},
|
|
||||||
{"PUT", "DELETE", "PUT"},
|
|
||||||
{"GET", "GET", "GET"},
|
|
||||||
{"HEAD", "HEAD", "HEAD"},
|
|
||||||
{"GET", "PUT", "GET"},
|
|
||||||
{"HEAD", "DELETE", "HEAD"},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, test := range tests {
|
|
||||||
h := HTTPMethodOverrideHandler(okHandler)
|
|
||||||
reqs := make([]*http.Request, 0, 2)
|
|
||||||
|
|
||||||
rHeader, err := http.NewRequest(test.Method, "/", nil)
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
}
|
|
||||||
rHeader.Header.Set(HTTPMethodOverrideHeader, test.OverrideMethod)
|
|
||||||
reqs = append(reqs, rHeader)
|
|
||||||
|
|
||||||
f := url.Values{HTTPMethodOverrideFormKey: []string{test.OverrideMethod}}
|
|
||||||
rForm, err := http.NewRequest(test.Method, "/", strings.NewReader(f.Encode()))
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
}
|
|
||||||
rForm.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
|
||||||
reqs = append(reqs, rForm)
|
|
||||||
|
|
||||||
for _, r := range reqs {
|
|
||||||
w := httptest.NewRecorder()
|
|
||||||
h.ServeHTTP(w, r)
|
|
||||||
if r.Method != test.ExpectedMethod {
|
|
||||||
t.Errorf("Expected %s, got %s", test.ExpectedMethod, r.Method)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
100
Godeps/_workspace/src/github.com/gorilla/handlers/proxy_headers_test.go
generated
vendored
100
Godeps/_workspace/src/github.com/gorilla/handlers/proxy_headers_test.go
generated
vendored
|
@ -1,100 +0,0 @@
|
||||||
package handlers
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net/http"
|
|
||||||
"net/http/httptest"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
type headerTable struct {
|
|
||||||
key string // header key
|
|
||||||
val string // header val
|
|
||||||
expected string // expected result
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestGetIP(t *testing.T) {
|
|
||||||
headers := []headerTable{
|
|
||||||
{xForwardedFor, "8.8.8.8", "8.8.8.8"}, // Single address
|
|
||||||
{xForwardedFor, "8.8.8.8, 8.8.4.4", "8.8.8.8"}, // Multiple
|
|
||||||
{xForwardedFor, "[2001:db8:cafe::17]:4711", "[2001:db8:cafe::17]:4711"}, // IPv6 address
|
|
||||||
{xForwardedFor, "", ""}, // None
|
|
||||||
{xRealIP, "8.8.8.8", "8.8.8.8"}, // Single address
|
|
||||||
{xRealIP, "8.8.8.8, 8.8.4.4", "8.8.8.8, 8.8.4.4"}, // Multiple
|
|
||||||
{xRealIP, "[2001:db8:cafe::17]:4711", "[2001:db8:cafe::17]:4711"}, // IPv6 address
|
|
||||||
{xRealIP, "", ""}, // None
|
|
||||||
{forwarded, `for="_gazonk"`, "_gazonk"}, // Hostname
|
|
||||||
{forwarded, `For="[2001:db8:cafe::17]:4711`, `[2001:db8:cafe::17]:4711`}, // IPv6 address
|
|
||||||
{forwarded, `for=192.0.2.60;proto=http;by=203.0.113.43`, `192.0.2.60`}, // Multiple params
|
|
||||||
{forwarded, `for=192.0.2.43, for=198.51.100.17`, "192.0.2.43"}, // Multiple params
|
|
||||||
{forwarded, `for="workstation.local",for=198.51.100.17`, "workstation.local"}, // Hostname
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, v := range headers {
|
|
||||||
req := &http.Request{
|
|
||||||
Header: http.Header{
|
|
||||||
v.key: []string{v.val},
|
|
||||||
}}
|
|
||||||
res := getIP(req)
|
|
||||||
if res != v.expected {
|
|
||||||
t.Fatalf("wrong header for %s: got %s want %s", v.key, res,
|
|
||||||
v.expected)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestGetScheme(t *testing.T) {
|
|
||||||
headers := []headerTable{
|
|
||||||
{xForwardedProto, "https", "https"},
|
|
||||||
{xForwardedProto, "http", "http"},
|
|
||||||
{xForwardedProto, "HTTP", "http"},
|
|
||||||
{forwarded, `For="[2001:db8:cafe::17]:4711`, ""}, // No proto
|
|
||||||
{forwarded, `for=192.0.2.43, for=198.51.100.17;proto=https`, "https"}, // Multiple params before proto
|
|
||||||
{forwarded, `for=172.32.10.15; proto=https;by=127.0.0.1`, "https"}, // Space before proto
|
|
||||||
{forwarded, `for=192.0.2.60;proto=http;by=203.0.113.43`, "http"}, // Multiple params
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, v := range headers {
|
|
||||||
req := &http.Request{
|
|
||||||
Header: http.Header{
|
|
||||||
v.key: []string{v.val},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
res := getScheme(req)
|
|
||||||
if res != v.expected {
|
|
||||||
t.Fatalf("wrong header for %s: got %s want %s", v.key, res,
|
|
||||||
v.expected)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test the middleware end-to-end
|
|
||||||
func TestProxyHeaders(t *testing.T) {
|
|
||||||
rr := httptest.NewRecorder()
|
|
||||||
r := newRequest("GET", "/")
|
|
||||||
|
|
||||||
r.Header.Set(xForwardedFor, "8.8.8.8")
|
|
||||||
r.Header.Set(xForwardedProto, "https")
|
|
||||||
|
|
||||||
var addr string
|
|
||||||
var proto string
|
|
||||||
ProxyHeaders(http.HandlerFunc(
|
|
||||||
func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
addr = r.RemoteAddr
|
|
||||||
proto = r.URL.Scheme
|
|
||||||
})).ServeHTTP(rr, r)
|
|
||||||
|
|
||||||
if rr.Code != http.StatusOK {
|
|
||||||
t.Fatalf("bad status: got %d want %d", rr.Code, http.StatusOK)
|
|
||||||
}
|
|
||||||
|
|
||||||
if addr != r.Header.Get(xForwardedFor) {
|
|
||||||
t.Fatalf("wrong address: got %s want %s", addr,
|
|
||||||
r.Header.Get(xForwardedFor))
|
|
||||||
}
|
|
||||||
|
|
||||||
if proto != r.Header.Get(xForwardedProto) {
|
|
||||||
t.Fatalf("wrong address: got %s want %s", proto,
|
|
||||||
r.Header.Get(xForwardedProto))
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
120
Godeps/_workspace/src/github.com/jonboulle/clockwork/clockwork_test.go
generated
vendored
120
Godeps/_workspace/src/github.com/jonboulle/clockwork/clockwork_test.go
generated
vendored
|
@ -1,120 +0,0 @@
|
||||||
package clockwork
|
|
||||||
|
|
||||||
import (
|
|
||||||
"reflect"
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestFakeClockAfter(t *testing.T) {
|
|
||||||
fc := &fakeClock{}
|
|
||||||
|
|
||||||
zero := fc.After(0)
|
|
||||||
select {
|
|
||||||
case <-zero:
|
|
||||||
default:
|
|
||||||
t.Errorf("zero did not return!")
|
|
||||||
}
|
|
||||||
one := fc.After(1)
|
|
||||||
two := fc.After(2)
|
|
||||||
six := fc.After(6)
|
|
||||||
ten := fc.After(10)
|
|
||||||
fc.Advance(1)
|
|
||||||
select {
|
|
||||||
case <-one:
|
|
||||||
default:
|
|
||||||
t.Errorf("one did not return!")
|
|
||||||
}
|
|
||||||
select {
|
|
||||||
case <-two:
|
|
||||||
t.Errorf("two returned prematurely!")
|
|
||||||
case <-six:
|
|
||||||
t.Errorf("six returned prematurely!")
|
|
||||||
case <-ten:
|
|
||||||
t.Errorf("ten returned prematurely!")
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
fc.Advance(1)
|
|
||||||
select {
|
|
||||||
case <-two:
|
|
||||||
default:
|
|
||||||
t.Errorf("two did not return!")
|
|
||||||
}
|
|
||||||
select {
|
|
||||||
case <-six:
|
|
||||||
t.Errorf("six returned prematurely!")
|
|
||||||
case <-ten:
|
|
||||||
t.Errorf("ten returned prematurely!")
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
fc.Advance(1)
|
|
||||||
select {
|
|
||||||
case <-six:
|
|
||||||
t.Errorf("six returned prematurely!")
|
|
||||||
case <-ten:
|
|
||||||
t.Errorf("ten returned prematurely!")
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
fc.Advance(3)
|
|
||||||
select {
|
|
||||||
case <-six:
|
|
||||||
default:
|
|
||||||
t.Errorf("six did not return!")
|
|
||||||
}
|
|
||||||
select {
|
|
||||||
case <-ten:
|
|
||||||
t.Errorf("ten returned prematurely!")
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
fc.Advance(100)
|
|
||||||
select {
|
|
||||||
case <-ten:
|
|
||||||
default:
|
|
||||||
t.Errorf("ten did not return!")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestNotifyBlockers(t *testing.T) {
|
|
||||||
b1 := &blocker{1, make(chan struct{})}
|
|
||||||
b2 := &blocker{2, make(chan struct{})}
|
|
||||||
b3 := &blocker{5, make(chan struct{})}
|
|
||||||
b4 := &blocker{10, make(chan struct{})}
|
|
||||||
b5 := &blocker{10, make(chan struct{})}
|
|
||||||
bs := []*blocker{b1, b2, b3, b4, b5}
|
|
||||||
bs1 := notifyBlockers(bs, 2)
|
|
||||||
if n := len(bs1); n != 4 {
|
|
||||||
t.Fatalf("got %d blockers, want %d", n, 4)
|
|
||||||
}
|
|
||||||
select {
|
|
||||||
case <-b2.ch:
|
|
||||||
case <-time.After(time.Second):
|
|
||||||
t.Fatalf("timed out waiting for channel close!")
|
|
||||||
}
|
|
||||||
bs2 := notifyBlockers(bs1, 10)
|
|
||||||
if n := len(bs2); n != 2 {
|
|
||||||
t.Fatalf("got %d blockers, want %d", n, 2)
|
|
||||||
}
|
|
||||||
select {
|
|
||||||
case <-b4.ch:
|
|
||||||
case <-time.After(time.Second):
|
|
||||||
t.Fatalf("timed out waiting for channel close!")
|
|
||||||
}
|
|
||||||
select {
|
|
||||||
case <-b5.ch:
|
|
||||||
case <-time.After(time.Second):
|
|
||||||
t.Fatalf("timed out waiting for channel close!")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestNewFakeClock(t *testing.T) {
|
|
||||||
fc := NewFakeClock()
|
|
||||||
now := fc.Now()
|
|
||||||
if now.IsZero() {
|
|
||||||
t.Fatalf("fakeClock.Now() fulfills IsZero")
|
|
||||||
}
|
|
||||||
|
|
||||||
now2 := fc.Now()
|
|
||||||
if !reflect.DeepEqual(now, now2) {
|
|
||||||
t.Fatalf("fakeClock.Now() returned different value: want=%#v got=%#v", now, now2)
|
|
||||||
}
|
|
||||||
}
|
|
49
Godeps/_workspace/src/github.com/jonboulle/clockwork/example_test.go
generated
vendored
49
Godeps/_workspace/src/github.com/jonboulle/clockwork/example_test.go
generated
vendored
|
@ -1,49 +0,0 @@
|
||||||
package clockwork
|
|
||||||
|
|
||||||
import (
|
|
||||||
"sync"
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
// my_func is an example of a time-dependent function, using an
|
|
||||||
// injected clock
|
|
||||||
func my_func(clock Clock, i *int) {
|
|
||||||
clock.Sleep(3 * time.Second)
|
|
||||||
*i += 1
|
|
||||||
}
|
|
||||||
|
|
||||||
// assert_state is an example of a state assertion in a test
|
|
||||||
func assert_state(t *testing.T, i, j int) {
|
|
||||||
if i != j {
|
|
||||||
t.Fatalf("i %d, j %d", i, j)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TestMyFunc tests my_func's behaviour with a FakeClock
|
|
||||||
func TestMyFunc(t *testing.T) {
|
|
||||||
var i int
|
|
||||||
c := NewFakeClock()
|
|
||||||
|
|
||||||
var wg sync.WaitGroup
|
|
||||||
wg.Add(1)
|
|
||||||
go func() {
|
|
||||||
my_func(c, &i)
|
|
||||||
wg.Done()
|
|
||||||
}()
|
|
||||||
|
|
||||||
// Wait until my_func is actually sleeping on the clock
|
|
||||||
c.BlockUntil(1)
|
|
||||||
|
|
||||||
// Assert the initial state
|
|
||||||
assert_state(t, i, 0)
|
|
||||||
|
|
||||||
// Now advance the clock forward in time
|
|
||||||
c.Advance(1 * time.Hour)
|
|
||||||
|
|
||||||
// Wait until the function completes
|
|
||||||
wg.Wait()
|
|
||||||
|
|
||||||
// Assert the final state
|
|
||||||
assert_state(t, i, 1)
|
|
||||||
}
|
|
92
Godeps/_workspace/src/github.com/julienschmidt/httprouter/path_test.go
generated
vendored
92
Godeps/_workspace/src/github.com/julienschmidt/httprouter/path_test.go
generated
vendored
|
@ -1,92 +0,0 @@
|
||||||
// Copyright 2013 Julien Schmidt. All rights reserved.
|
|
||||||
// Based on the path package, Copyright 2009 The Go Authors.
|
|
||||||
// Use of this source code is governed by a BSD-style license that can be found
|
|
||||||
// in the LICENSE file.
|
|
||||||
|
|
||||||
package httprouter
|
|
||||||
|
|
||||||
import (
|
|
||||||
"runtime"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
var cleanTests = []struct {
|
|
||||||
path, result string
|
|
||||||
}{
|
|
||||||
// Already clean
|
|
||||||
{"/", "/"},
|
|
||||||
{"/abc", "/abc"},
|
|
||||||
{"/a/b/c", "/a/b/c"},
|
|
||||||
{"/abc/", "/abc/"},
|
|
||||||
{"/a/b/c/", "/a/b/c/"},
|
|
||||||
|
|
||||||
// missing root
|
|
||||||
{"", "/"},
|
|
||||||
{"abc", "/abc"},
|
|
||||||
{"abc/def", "/abc/def"},
|
|
||||||
{"a/b/c", "/a/b/c"},
|
|
||||||
|
|
||||||
// Remove doubled slash
|
|
||||||
{"//", "/"},
|
|
||||||
{"/abc//", "/abc/"},
|
|
||||||
{"/abc/def//", "/abc/def/"},
|
|
||||||
{"/a/b/c//", "/a/b/c/"},
|
|
||||||
{"/abc//def//ghi", "/abc/def/ghi"},
|
|
||||||
{"//abc", "/abc"},
|
|
||||||
{"///abc", "/abc"},
|
|
||||||
{"//abc//", "/abc/"},
|
|
||||||
|
|
||||||
// Remove . elements
|
|
||||||
{".", "/"},
|
|
||||||
{"./", "/"},
|
|
||||||
{"/abc/./def", "/abc/def"},
|
|
||||||
{"/./abc/def", "/abc/def"},
|
|
||||||
{"/abc/.", "/abc/"},
|
|
||||||
|
|
||||||
// Remove .. elements
|
|
||||||
{"..", "/"},
|
|
||||||
{"../", "/"},
|
|
||||||
{"../../", "/"},
|
|
||||||
{"../..", "/"},
|
|
||||||
{"../../abc", "/abc"},
|
|
||||||
{"/abc/def/ghi/../jkl", "/abc/def/jkl"},
|
|
||||||
{"/abc/def/../ghi/../jkl", "/abc/jkl"},
|
|
||||||
{"/abc/def/..", "/abc"},
|
|
||||||
{"/abc/def/../..", "/"},
|
|
||||||
{"/abc/def/../../..", "/"},
|
|
||||||
{"/abc/def/../../..", "/"},
|
|
||||||
{"/abc/def/../../../ghi/jkl/../../../mno", "/mno"},
|
|
||||||
|
|
||||||
// Combinations
|
|
||||||
{"abc/./../def", "/def"},
|
|
||||||
{"abc//./../def", "/def"},
|
|
||||||
{"abc/../../././../def", "/def"},
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestPathClean(t *testing.T) {
|
|
||||||
for _, test := range cleanTests {
|
|
||||||
if s := CleanPath(test.path); s != test.result {
|
|
||||||
t.Errorf("CleanPath(%q) = %q, want %q", test.path, s, test.result)
|
|
||||||
}
|
|
||||||
if s := CleanPath(test.result); s != test.result {
|
|
||||||
t.Errorf("CleanPath(%q) = %q, want %q", test.result, s, test.result)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestPathCleanMallocs(t *testing.T) {
|
|
||||||
if testing.Short() {
|
|
||||||
t.Skip("skipping malloc count in short mode")
|
|
||||||
}
|
|
||||||
if runtime.GOMAXPROCS(0) > 1 {
|
|
||||||
t.Log("skipping AllocsPerRun checks; GOMAXPROCS>1")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, test := range cleanTests {
|
|
||||||
allocs := testing.AllocsPerRun(100, func() { CleanPath(test.result) })
|
|
||||||
if allocs > 0 {
|
|
||||||
t.Errorf("CleanPath(%q): %v allocs, want zero", test.result, allocs)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
378
Godeps/_workspace/src/github.com/julienschmidt/httprouter/router_test.go
generated
vendored
378
Godeps/_workspace/src/github.com/julienschmidt/httprouter/router_test.go
generated
vendored
|
@ -1,378 +0,0 @@
|
||||||
// Copyright 2013 Julien Schmidt. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style license that can be found
|
|
||||||
// in the LICENSE file.
|
|
||||||
|
|
||||||
package httprouter
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"net/http"
|
|
||||||
"net/http/httptest"
|
|
||||||
"reflect"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
type mockResponseWriter struct{}
|
|
||||||
|
|
||||||
func (m *mockResponseWriter) Header() (h http.Header) {
|
|
||||||
return http.Header{}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *mockResponseWriter) Write(p []byte) (n int, err error) {
|
|
||||||
return len(p), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *mockResponseWriter) WriteString(s string) (n int, err error) {
|
|
||||||
return len(s), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *mockResponseWriter) WriteHeader(int) {}
|
|
||||||
|
|
||||||
func TestParams(t *testing.T) {
|
|
||||||
ps := Params{
|
|
||||||
Param{"param1", "value1"},
|
|
||||||
Param{"param2", "value2"},
|
|
||||||
Param{"param3", "value3"},
|
|
||||||
}
|
|
||||||
for i := range ps {
|
|
||||||
if val := ps.ByName(ps[i].Key); val != ps[i].Value {
|
|
||||||
t.Errorf("Wrong value for %s: Got %s; Want %s", ps[i].Key, val, ps[i].Value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if val := ps.ByName("noKey"); val != "" {
|
|
||||||
t.Errorf("Expected empty string for not found key; got: %s", val)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestRouter(t *testing.T) {
|
|
||||||
router := New()
|
|
||||||
|
|
||||||
routed := false
|
|
||||||
router.Handle("GET", "/user/:name", func(w http.ResponseWriter, r *http.Request, ps Params) {
|
|
||||||
routed = true
|
|
||||||
want := Params{Param{"name", "gopher"}}
|
|
||||||
if !reflect.DeepEqual(ps, want) {
|
|
||||||
t.Fatalf("wrong wildcard values: want %v, got %v", want, ps)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
w := new(mockResponseWriter)
|
|
||||||
|
|
||||||
req, _ := http.NewRequest("GET", "/user/gopher", nil)
|
|
||||||
router.ServeHTTP(w, req)
|
|
||||||
|
|
||||||
if !routed {
|
|
||||||
t.Fatal("routing failed")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type handlerStruct struct {
|
|
||||||
handeled *bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h handlerStruct) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|
||||||
*h.handeled = true
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestRouterAPI(t *testing.T) {
|
|
||||||
var get, head, options, post, put, patch, delete, handler, handlerFunc bool
|
|
||||||
|
|
||||||
httpHandler := handlerStruct{&handler}
|
|
||||||
|
|
||||||
router := New()
|
|
||||||
router.GET("/GET", func(w http.ResponseWriter, r *http.Request, _ Params) {
|
|
||||||
get = true
|
|
||||||
})
|
|
||||||
router.HEAD("/GET", func(w http.ResponseWriter, r *http.Request, _ Params) {
|
|
||||||
head = true
|
|
||||||
})
|
|
||||||
router.OPTIONS("/GET", func(w http.ResponseWriter, r *http.Request, _ Params) {
|
|
||||||
options = true
|
|
||||||
})
|
|
||||||
router.POST("/POST", func(w http.ResponseWriter, r *http.Request, _ Params) {
|
|
||||||
post = true
|
|
||||||
})
|
|
||||||
router.PUT("/PUT", func(w http.ResponseWriter, r *http.Request, _ Params) {
|
|
||||||
put = true
|
|
||||||
})
|
|
||||||
router.PATCH("/PATCH", func(w http.ResponseWriter, r *http.Request, _ Params) {
|
|
||||||
patch = true
|
|
||||||
})
|
|
||||||
router.DELETE("/DELETE", func(w http.ResponseWriter, r *http.Request, _ Params) {
|
|
||||||
delete = true
|
|
||||||
})
|
|
||||||
router.Handler("GET", "/Handler", httpHandler)
|
|
||||||
router.HandlerFunc("GET", "/HandlerFunc", func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
handlerFunc = true
|
|
||||||
})
|
|
||||||
|
|
||||||
w := new(mockResponseWriter)
|
|
||||||
|
|
||||||
r, _ := http.NewRequest("GET", "/GET", nil)
|
|
||||||
router.ServeHTTP(w, r)
|
|
||||||
if !get {
|
|
||||||
t.Error("routing GET failed")
|
|
||||||
}
|
|
||||||
|
|
||||||
r, _ = http.NewRequest("HEAD", "/GET", nil)
|
|
||||||
router.ServeHTTP(w, r)
|
|
||||||
if !head {
|
|
||||||
t.Error("routing HEAD failed")
|
|
||||||
}
|
|
||||||
|
|
||||||
r, _ = http.NewRequest("OPTIONS", "/GET", nil)
|
|
||||||
router.ServeHTTP(w, r)
|
|
||||||
if !options {
|
|
||||||
t.Error("routing OPTIONS failed")
|
|
||||||
}
|
|
||||||
|
|
||||||
r, _ = http.NewRequest("POST", "/POST", nil)
|
|
||||||
router.ServeHTTP(w, r)
|
|
||||||
if !post {
|
|
||||||
t.Error("routing POST failed")
|
|
||||||
}
|
|
||||||
|
|
||||||
r, _ = http.NewRequest("PUT", "/PUT", nil)
|
|
||||||
router.ServeHTTP(w, r)
|
|
||||||
if !put {
|
|
||||||
t.Error("routing PUT failed")
|
|
||||||
}
|
|
||||||
|
|
||||||
r, _ = http.NewRequest("PATCH", "/PATCH", nil)
|
|
||||||
router.ServeHTTP(w, r)
|
|
||||||
if !patch {
|
|
||||||
t.Error("routing PATCH failed")
|
|
||||||
}
|
|
||||||
|
|
||||||
r, _ = http.NewRequest("DELETE", "/DELETE", nil)
|
|
||||||
router.ServeHTTP(w, r)
|
|
||||||
if !delete {
|
|
||||||
t.Error("routing DELETE failed")
|
|
||||||
}
|
|
||||||
|
|
||||||
r, _ = http.NewRequest("GET", "/Handler", nil)
|
|
||||||
router.ServeHTTP(w, r)
|
|
||||||
if !handler {
|
|
||||||
t.Error("routing Handler failed")
|
|
||||||
}
|
|
||||||
|
|
||||||
r, _ = http.NewRequest("GET", "/HandlerFunc", nil)
|
|
||||||
router.ServeHTTP(w, r)
|
|
||||||
if !handlerFunc {
|
|
||||||
t.Error("routing HandlerFunc failed")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestRouterRoot(t *testing.T) {
|
|
||||||
router := New()
|
|
||||||
recv := catchPanic(func() {
|
|
||||||
router.GET("noSlashRoot", nil)
|
|
||||||
})
|
|
||||||
if recv == nil {
|
|
||||||
t.Fatal("registering path not beginning with '/' did not panic")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestRouterNotAllowed(t *testing.T) {
|
|
||||||
handlerFunc := func(_ http.ResponseWriter, _ *http.Request, _ Params) {}
|
|
||||||
|
|
||||||
router := New()
|
|
||||||
router.POST("/path", handlerFunc)
|
|
||||||
|
|
||||||
// Test not allowed
|
|
||||||
r, _ := http.NewRequest("GET", "/path", nil)
|
|
||||||
w := httptest.NewRecorder()
|
|
||||||
router.ServeHTTP(w, r)
|
|
||||||
if !(w.Code == http.StatusMethodNotAllowed) {
|
|
||||||
t.Errorf("NotAllowed handling failed: Code=%d, Header=%v", w.Code, w.Header())
|
|
||||||
}
|
|
||||||
|
|
||||||
w = httptest.NewRecorder()
|
|
||||||
responseText := "custom method"
|
|
||||||
router.MethodNotAllowed = func(w http.ResponseWriter, req *http.Request) {
|
|
||||||
w.WriteHeader(http.StatusTeapot)
|
|
||||||
w.Write([]byte(responseText))
|
|
||||||
}
|
|
||||||
router.ServeHTTP(w, r)
|
|
||||||
if got := w.Body.String(); !(got == responseText) {
|
|
||||||
t.Errorf("unexpected response got %q want %q", got, responseText)
|
|
||||||
}
|
|
||||||
if w.Code != http.StatusTeapot {
|
|
||||||
t.Errorf("unexpected response code %d want %d", w.Code, http.StatusTeapot)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestRouterNotFound(t *testing.T) {
|
|
||||||
handlerFunc := func(_ http.ResponseWriter, _ *http.Request, _ Params) {}
|
|
||||||
|
|
||||||
router := New()
|
|
||||||
router.GET("/path", handlerFunc)
|
|
||||||
router.GET("/dir/", handlerFunc)
|
|
||||||
router.GET("/", handlerFunc)
|
|
||||||
|
|
||||||
testRoutes := []struct {
|
|
||||||
route string
|
|
||||||
code int
|
|
||||||
header string
|
|
||||||
}{
|
|
||||||
{"/path/", 301, "map[Location:[/path]]"}, // TSR -/
|
|
||||||
{"/dir", 301, "map[Location:[/dir/]]"}, // TSR +/
|
|
||||||
{"", 301, "map[Location:[/]]"}, // TSR +/
|
|
||||||
{"/PATH", 301, "map[Location:[/path]]"}, // Fixed Case
|
|
||||||
{"/DIR/", 301, "map[Location:[/dir/]]"}, // Fixed Case
|
|
||||||
{"/PATH/", 301, "map[Location:[/path]]"}, // Fixed Case -/
|
|
||||||
{"/DIR", 301, "map[Location:[/dir/]]"}, // Fixed Case +/
|
|
||||||
{"/../path", 301, "map[Location:[/path]]"}, // CleanPath
|
|
||||||
{"/nope", 404, ""}, // NotFound
|
|
||||||
}
|
|
||||||
for _, tr := range testRoutes {
|
|
||||||
r, _ := http.NewRequest("GET", tr.route, nil)
|
|
||||||
w := httptest.NewRecorder()
|
|
||||||
router.ServeHTTP(w, r)
|
|
||||||
if !(w.Code == tr.code && (w.Code == 404 || fmt.Sprint(w.Header()) == tr.header)) {
|
|
||||||
t.Errorf("NotFound handling route %s failed: Code=%d, Header=%v", tr.route, w.Code, w.Header())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test custom not found handler
|
|
||||||
var notFound bool
|
|
||||||
router.NotFound = func(rw http.ResponseWriter, r *http.Request) {
|
|
||||||
rw.WriteHeader(404)
|
|
||||||
notFound = true
|
|
||||||
}
|
|
||||||
r, _ := http.NewRequest("GET", "/nope", nil)
|
|
||||||
w := httptest.NewRecorder()
|
|
||||||
router.ServeHTTP(w, r)
|
|
||||||
if !(w.Code == 404 && notFound == true) {
|
|
||||||
t.Errorf("Custom NotFound handler failed: Code=%d, Header=%v", w.Code, w.Header())
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test other method than GET (want 307 instead of 301)
|
|
||||||
router.PATCH("/path", handlerFunc)
|
|
||||||
r, _ = http.NewRequest("PATCH", "/path/", nil)
|
|
||||||
w = httptest.NewRecorder()
|
|
||||||
router.ServeHTTP(w, r)
|
|
||||||
if !(w.Code == 307 && fmt.Sprint(w.Header()) == "map[Location:[/path]]") {
|
|
||||||
t.Errorf("Custom NotFound handler failed: Code=%d, Header=%v", w.Code, w.Header())
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test special case where no node for the prefix "/" exists
|
|
||||||
router = New()
|
|
||||||
router.GET("/a", handlerFunc)
|
|
||||||
r, _ = http.NewRequest("GET", "/", nil)
|
|
||||||
w = httptest.NewRecorder()
|
|
||||||
router.ServeHTTP(w, r)
|
|
||||||
if !(w.Code == 404) {
|
|
||||||
t.Errorf("NotFound handling route / failed: Code=%d", w.Code)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestRouterPanicHandler(t *testing.T) {
|
|
||||||
router := New()
|
|
||||||
panicHandled := false
|
|
||||||
|
|
||||||
router.PanicHandler = func(rw http.ResponseWriter, r *http.Request, p interface{}) {
|
|
||||||
panicHandled = true
|
|
||||||
}
|
|
||||||
|
|
||||||
router.Handle("PUT", "/user/:name", func(_ http.ResponseWriter, _ *http.Request, _ Params) {
|
|
||||||
panic("oops!")
|
|
||||||
})
|
|
||||||
|
|
||||||
w := new(mockResponseWriter)
|
|
||||||
req, _ := http.NewRequest("PUT", "/user/gopher", nil)
|
|
||||||
|
|
||||||
defer func() {
|
|
||||||
if rcv := recover(); rcv != nil {
|
|
||||||
t.Fatal("handling panic failed")
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
router.ServeHTTP(w, req)
|
|
||||||
|
|
||||||
if !panicHandled {
|
|
||||||
t.Fatal("simulating failed")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestRouterLookup(t *testing.T) {
|
|
||||||
routed := false
|
|
||||||
wantHandle := func(_ http.ResponseWriter, _ *http.Request, _ Params) {
|
|
||||||
routed = true
|
|
||||||
}
|
|
||||||
wantParams := Params{Param{"name", "gopher"}}
|
|
||||||
|
|
||||||
router := New()
|
|
||||||
|
|
||||||
// try empty router first
|
|
||||||
handle, _, tsr := router.Lookup("GET", "/nope")
|
|
||||||
if handle != nil {
|
|
||||||
t.Fatalf("Got handle for unregistered pattern: %v", handle)
|
|
||||||
}
|
|
||||||
if tsr {
|
|
||||||
t.Error("Got wrong TSR recommendation!")
|
|
||||||
}
|
|
||||||
|
|
||||||
// insert route and try again
|
|
||||||
router.GET("/user/:name", wantHandle)
|
|
||||||
|
|
||||||
handle, params, tsr := router.Lookup("GET", "/user/gopher")
|
|
||||||
if handle == nil {
|
|
||||||
t.Fatal("Got no handle!")
|
|
||||||
} else {
|
|
||||||
handle(nil, nil, nil)
|
|
||||||
if !routed {
|
|
||||||
t.Fatal("Routing failed!")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !reflect.DeepEqual(params, wantParams) {
|
|
||||||
t.Fatalf("Wrong parameter values: want %v, got %v", wantParams, params)
|
|
||||||
}
|
|
||||||
|
|
||||||
handle, _, tsr = router.Lookup("GET", "/user/gopher/")
|
|
||||||
if handle != nil {
|
|
||||||
t.Fatalf("Got handle for unregistered pattern: %v", handle)
|
|
||||||
}
|
|
||||||
if !tsr {
|
|
||||||
t.Error("Got no TSR recommendation!")
|
|
||||||
}
|
|
||||||
|
|
||||||
handle, _, tsr = router.Lookup("GET", "/nope")
|
|
||||||
if handle != nil {
|
|
||||||
t.Fatalf("Got handle for unregistered pattern: %v", handle)
|
|
||||||
}
|
|
||||||
if tsr {
|
|
||||||
t.Error("Got wrong TSR recommendation!")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type mockFileSystem struct {
|
|
||||||
opened bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func (mfs *mockFileSystem) Open(name string) (http.File, error) {
|
|
||||||
mfs.opened = true
|
|
||||||
return nil, errors.New("this is just a mock")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestRouterServeFiles(t *testing.T) {
|
|
||||||
router := New()
|
|
||||||
mfs := &mockFileSystem{}
|
|
||||||
|
|
||||||
recv := catchPanic(func() {
|
|
||||||
router.ServeFiles("/noFilepath", mfs)
|
|
||||||
})
|
|
||||||
if recv == nil {
|
|
||||||
t.Fatal("registering path not ending with '*filepath' did not panic")
|
|
||||||
}
|
|
||||||
|
|
||||||
router.ServeFiles("/*filepath", mfs)
|
|
||||||
w := new(mockResponseWriter)
|
|
||||||
r, _ := http.NewRequest("GET", "/favicon.ico", nil)
|
|
||||||
router.ServeHTTP(w, r)
|
|
||||||
if !mfs.opened {
|
|
||||||
t.Error("serving file failed")
|
|
||||||
}
|
|
||||||
}
|
|
611
Godeps/_workspace/src/github.com/julienschmidt/httprouter/tree_test.go
generated
vendored
611
Godeps/_workspace/src/github.com/julienschmidt/httprouter/tree_test.go
generated
vendored
|
@ -1,611 +0,0 @@
|
||||||
// Copyright 2013 Julien Schmidt. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style license that can be found
|
|
||||||
// in the LICENSE file.
|
|
||||||
|
|
||||||
package httprouter
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"net/http"
|
|
||||||
"reflect"
|
|
||||||
"strings"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func printChildren(n *node, prefix string) {
|
|
||||||
fmt.Printf(" %02d:%02d %s%s[%d] %v %t %d \r\n", n.priority, n.maxParams, prefix, n.path, len(n.children), n.handle, n.wildChild, n.nType)
|
|
||||||
for l := len(n.path); l > 0; l-- {
|
|
||||||
prefix += " "
|
|
||||||
}
|
|
||||||
for _, child := range n.children {
|
|
||||||
printChildren(child, prefix)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Used as a workaround since we can't compare functions or their adresses
|
|
||||||
var fakeHandlerValue string
|
|
||||||
|
|
||||||
func fakeHandler(val string) Handle {
|
|
||||||
return func(http.ResponseWriter, *http.Request, Params) {
|
|
||||||
fakeHandlerValue = val
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type testRequests []struct {
|
|
||||||
path string
|
|
||||||
nilHandler bool
|
|
||||||
route string
|
|
||||||
ps Params
|
|
||||||
}
|
|
||||||
|
|
||||||
func checkRequests(t *testing.T, tree *node, requests testRequests) {
|
|
||||||
for _, request := range requests {
|
|
||||||
handler, ps, _ := tree.getValue(request.path)
|
|
||||||
|
|
||||||
if handler == nil {
|
|
||||||
if !request.nilHandler {
|
|
||||||
t.Errorf("handle mismatch for route '%s': Expected non-nil handle", request.path)
|
|
||||||
}
|
|
||||||
} else if request.nilHandler {
|
|
||||||
t.Errorf("handle mismatch for route '%s': Expected nil handle", request.path)
|
|
||||||
} else {
|
|
||||||
handler(nil, nil, nil)
|
|
||||||
if fakeHandlerValue != request.route {
|
|
||||||
t.Errorf("handle mismatch for route '%s': Wrong handle (%s != %s)", request.path, fakeHandlerValue, request.route)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !reflect.DeepEqual(ps, request.ps) {
|
|
||||||
t.Errorf("Params mismatch for route '%s'", request.path)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func checkPriorities(t *testing.T, n *node) uint32 {
|
|
||||||
var prio uint32
|
|
||||||
for i := range n.children {
|
|
||||||
prio += checkPriorities(t, n.children[i])
|
|
||||||
}
|
|
||||||
|
|
||||||
if n.handle != nil {
|
|
||||||
prio++
|
|
||||||
}
|
|
||||||
|
|
||||||
if n.priority != prio {
|
|
||||||
t.Errorf(
|
|
||||||
"priority mismatch for node '%s': is %d, should be %d",
|
|
||||||
n.path, n.priority, prio,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
return prio
|
|
||||||
}
|
|
||||||
|
|
||||||
func checkMaxParams(t *testing.T, n *node) uint8 {
|
|
||||||
var maxParams uint8
|
|
||||||
for i := range n.children {
|
|
||||||
params := checkMaxParams(t, n.children[i])
|
|
||||||
if params > maxParams {
|
|
||||||
maxParams = params
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if n.nType != static && !n.wildChild {
|
|
||||||
maxParams++
|
|
||||||
}
|
|
||||||
|
|
||||||
if n.maxParams != maxParams {
|
|
||||||
t.Errorf(
|
|
||||||
"maxParams mismatch for node '%s': is %d, should be %d",
|
|
||||||
n.path, n.maxParams, maxParams,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
return maxParams
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCountParams(t *testing.T) {
|
|
||||||
if countParams("/path/:param1/static/*catch-all") != 2 {
|
|
||||||
t.Fail()
|
|
||||||
}
|
|
||||||
if countParams(strings.Repeat("/:param", 256)) != 255 {
|
|
||||||
t.Fail()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTreeAddAndGet(t *testing.T) {
|
|
||||||
tree := &node{}
|
|
||||||
|
|
||||||
routes := [...]string{
|
|
||||||
"/hi",
|
|
||||||
"/contact",
|
|
||||||
"/co",
|
|
||||||
"/c",
|
|
||||||
"/a",
|
|
||||||
"/ab",
|
|
||||||
"/doc/",
|
|
||||||
"/doc/go_faq.html",
|
|
||||||
"/doc/go1.html",
|
|
||||||
"/α",
|
|
||||||
"/β",
|
|
||||||
}
|
|
||||||
for _, route := range routes {
|
|
||||||
tree.addRoute(route, fakeHandler(route))
|
|
||||||
}
|
|
||||||
|
|
||||||
//printChildren(tree, "")
|
|
||||||
|
|
||||||
checkRequests(t, tree, testRequests{
|
|
||||||
{"/a", false, "/a", nil},
|
|
||||||
{"/", true, "", nil},
|
|
||||||
{"/hi", false, "/hi", nil},
|
|
||||||
{"/contact", false, "/contact", nil},
|
|
||||||
{"/co", false, "/co", nil},
|
|
||||||
{"/con", true, "", nil}, // key mismatch
|
|
||||||
{"/cona", true, "", nil}, // key mismatch
|
|
||||||
{"/no", true, "", nil}, // no matching child
|
|
||||||
{"/ab", false, "/ab", nil},
|
|
||||||
{"/α", false, "/α", nil},
|
|
||||||
{"/β", false, "/β", nil},
|
|
||||||
})
|
|
||||||
|
|
||||||
checkPriorities(t, tree)
|
|
||||||
checkMaxParams(t, tree)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTreeWildcard(t *testing.T) {
|
|
||||||
tree := &node{}
|
|
||||||
|
|
||||||
routes := [...]string{
|
|
||||||
"/",
|
|
||||||
"/cmd/:tool/:sub",
|
|
||||||
"/cmd/:tool/",
|
|
||||||
"/src/*filepath",
|
|
||||||
"/search/",
|
|
||||||
"/search/:query",
|
|
||||||
"/user_:name",
|
|
||||||
"/user_:name/about",
|
|
||||||
"/files/:dir/*filepath",
|
|
||||||
"/doc/",
|
|
||||||
"/doc/go_faq.html",
|
|
||||||
"/doc/go1.html",
|
|
||||||
"/info/:user/public",
|
|
||||||
"/info/:user/project/:project",
|
|
||||||
}
|
|
||||||
for _, route := range routes {
|
|
||||||
tree.addRoute(route, fakeHandler(route))
|
|
||||||
}
|
|
||||||
|
|
||||||
//printChildren(tree, "")
|
|
||||||
|
|
||||||
checkRequests(t, tree, testRequests{
|
|
||||||
{"/", false, "/", nil},
|
|
||||||
{"/cmd/test/", false, "/cmd/:tool/", Params{Param{"tool", "test"}}},
|
|
||||||
{"/cmd/test", true, "", Params{Param{"tool", "test"}}},
|
|
||||||
{"/cmd/test/3", false, "/cmd/:tool/:sub", Params{Param{"tool", "test"}, Param{"sub", "3"}}},
|
|
||||||
{"/src/", false, "/src/*filepath", Params{Param{"filepath", "/"}}},
|
|
||||||
{"/src/some/file.png", false, "/src/*filepath", Params{Param{"filepath", "/some/file.png"}}},
|
|
||||||
{"/search/", false, "/search/", nil},
|
|
||||||
{"/search/someth!ng+in+ünìcodé", false, "/search/:query", Params{Param{"query", "someth!ng+in+ünìcodé"}}},
|
|
||||||
{"/search/someth!ng+in+ünìcodé/", true, "", Params{Param{"query", "someth!ng+in+ünìcodé"}}},
|
|
||||||
{"/user_gopher", false, "/user_:name", Params{Param{"name", "gopher"}}},
|
|
||||||
{"/user_gopher/about", false, "/user_:name/about", Params{Param{"name", "gopher"}}},
|
|
||||||
{"/files/js/inc/framework.js", false, "/files/:dir/*filepath", Params{Param{"dir", "js"}, Param{"filepath", "/inc/framework.js"}}},
|
|
||||||
{"/info/gordon/public", false, "/info/:user/public", Params{Param{"user", "gordon"}}},
|
|
||||||
{"/info/gordon/project/go", false, "/info/:user/project/:project", Params{Param{"user", "gordon"}, Param{"project", "go"}}},
|
|
||||||
})
|
|
||||||
|
|
||||||
checkPriorities(t, tree)
|
|
||||||
checkMaxParams(t, tree)
|
|
||||||
}
|
|
||||||
|
|
||||||
func catchPanic(testFunc func()) (recv interface{}) {
|
|
||||||
defer func() {
|
|
||||||
recv = recover()
|
|
||||||
}()
|
|
||||||
|
|
||||||
testFunc()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
type testRoute struct {
|
|
||||||
path string
|
|
||||||
conflict bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func testRoutes(t *testing.T, routes []testRoute) {
|
|
||||||
tree := &node{}
|
|
||||||
|
|
||||||
for _, route := range routes {
|
|
||||||
recv := catchPanic(func() {
|
|
||||||
tree.addRoute(route.path, nil)
|
|
||||||
})
|
|
||||||
|
|
||||||
if route.conflict {
|
|
||||||
if recv == nil {
|
|
||||||
t.Errorf("no panic for conflicting route '%s'", route.path)
|
|
||||||
}
|
|
||||||
} else if recv != nil {
|
|
||||||
t.Errorf("unexpected panic for route '%s': %v", route.path, recv)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//printChildren(tree, "")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTreeWildcardConflict(t *testing.T) {
|
|
||||||
routes := []testRoute{
|
|
||||||
{"/cmd/:tool/:sub", false},
|
|
||||||
{"/cmd/vet", true},
|
|
||||||
{"/src/*filepath", false},
|
|
||||||
{"/src/*filepathx", true},
|
|
||||||
{"/src/", true},
|
|
||||||
{"/src1/", false},
|
|
||||||
{"/src1/*filepath", true},
|
|
||||||
{"/src2*filepath", true},
|
|
||||||
{"/search/:query", false},
|
|
||||||
{"/search/invalid", true},
|
|
||||||
{"/user_:name", false},
|
|
||||||
{"/user_x", true},
|
|
||||||
{"/user_:name", false},
|
|
||||||
{"/id:id", false},
|
|
||||||
{"/id/:id", true},
|
|
||||||
}
|
|
||||||
testRoutes(t, routes)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTreeChildConflict(t *testing.T) {
|
|
||||||
routes := []testRoute{
|
|
||||||
{"/cmd/vet", false},
|
|
||||||
{"/cmd/:tool/:sub", true},
|
|
||||||
{"/src/AUTHORS", false},
|
|
||||||
{"/src/*filepath", true},
|
|
||||||
{"/user_x", false},
|
|
||||||
{"/user_:name", true},
|
|
||||||
{"/id/:id", false},
|
|
||||||
{"/id:id", true},
|
|
||||||
{"/:id", true},
|
|
||||||
{"/*filepath", true},
|
|
||||||
}
|
|
||||||
testRoutes(t, routes)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTreeDupliatePath(t *testing.T) {
|
|
||||||
tree := &node{}
|
|
||||||
|
|
||||||
routes := [...]string{
|
|
||||||
"/",
|
|
||||||
"/doc/",
|
|
||||||
"/src/*filepath",
|
|
||||||
"/search/:query",
|
|
||||||
"/user_:name",
|
|
||||||
}
|
|
||||||
for _, route := range routes {
|
|
||||||
recv := catchPanic(func() {
|
|
||||||
tree.addRoute(route, fakeHandler(route))
|
|
||||||
})
|
|
||||||
if recv != nil {
|
|
||||||
t.Fatalf("panic inserting route '%s': %v", route, recv)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add again
|
|
||||||
recv = catchPanic(func() {
|
|
||||||
tree.addRoute(route, nil)
|
|
||||||
})
|
|
||||||
if recv == nil {
|
|
||||||
t.Fatalf("no panic while inserting duplicate route '%s", route)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//printChildren(tree, "")
|
|
||||||
|
|
||||||
checkRequests(t, tree, testRequests{
|
|
||||||
{"/", false, "/", nil},
|
|
||||||
{"/doc/", false, "/doc/", nil},
|
|
||||||
{"/src/some/file.png", false, "/src/*filepath", Params{Param{"filepath", "/some/file.png"}}},
|
|
||||||
{"/search/someth!ng+in+ünìcodé", false, "/search/:query", Params{Param{"query", "someth!ng+in+ünìcodé"}}},
|
|
||||||
{"/user_gopher", false, "/user_:name", Params{Param{"name", "gopher"}}},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestEmptyWildcardName(t *testing.T) {
|
|
||||||
tree := &node{}
|
|
||||||
|
|
||||||
routes := [...]string{
|
|
||||||
"/user:",
|
|
||||||
"/user:/",
|
|
||||||
"/cmd/:/",
|
|
||||||
"/src/*",
|
|
||||||
}
|
|
||||||
for _, route := range routes {
|
|
||||||
recv := catchPanic(func() {
|
|
||||||
tree.addRoute(route, nil)
|
|
||||||
})
|
|
||||||
if recv == nil {
|
|
||||||
t.Fatalf("no panic while inserting route with empty wildcard name '%s", route)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTreeCatchAllConflict(t *testing.T) {
|
|
||||||
routes := []testRoute{
|
|
||||||
{"/src/*filepath/x", true},
|
|
||||||
{"/src2/", false},
|
|
||||||
{"/src2/*filepath/x", true},
|
|
||||||
}
|
|
||||||
testRoutes(t, routes)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTreeCatchAllConflictRoot(t *testing.T) {
|
|
||||||
routes := []testRoute{
|
|
||||||
{"/", false},
|
|
||||||
{"/*filepath", true},
|
|
||||||
}
|
|
||||||
testRoutes(t, routes)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTreeDoubleWildcard(t *testing.T) {
|
|
||||||
const panicMsg = "only one wildcard per path segment is allowed"
|
|
||||||
|
|
||||||
routes := [...]string{
|
|
||||||
"/:foo:bar",
|
|
||||||
"/:foo:bar/",
|
|
||||||
"/:foo*bar",
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, route := range routes {
|
|
||||||
tree := &node{}
|
|
||||||
recv := catchPanic(func() {
|
|
||||||
tree.addRoute(route, nil)
|
|
||||||
})
|
|
||||||
|
|
||||||
if rs, ok := recv.(string); !ok || !strings.HasPrefix(rs, panicMsg) {
|
|
||||||
t.Fatalf(`"Expected panic "%s" for route '%s', got "%v"`, panicMsg, route, recv)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*func TestTreeDuplicateWildcard(t *testing.T) {
|
|
||||||
tree := &node{}
|
|
||||||
|
|
||||||
routes := [...]string{
|
|
||||||
"/:id/:name/:id",
|
|
||||||
}
|
|
||||||
for _, route := range routes {
|
|
||||||
...
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
|
|
||||||
func TestTreeTrailingSlashRedirect(t *testing.T) {
|
|
||||||
tree := &node{}
|
|
||||||
|
|
||||||
routes := [...]string{
|
|
||||||
"/hi",
|
|
||||||
"/b/",
|
|
||||||
"/search/:query",
|
|
||||||
"/cmd/:tool/",
|
|
||||||
"/src/*filepath",
|
|
||||||
"/x",
|
|
||||||
"/x/y",
|
|
||||||
"/y/",
|
|
||||||
"/y/z",
|
|
||||||
"/0/:id",
|
|
||||||
"/0/:id/1",
|
|
||||||
"/1/:id/",
|
|
||||||
"/1/:id/2",
|
|
||||||
"/aa",
|
|
||||||
"/a/",
|
|
||||||
"/doc",
|
|
||||||
"/doc/go_faq.html",
|
|
||||||
"/doc/go1.html",
|
|
||||||
"/no/a",
|
|
||||||
"/no/b",
|
|
||||||
"/api/hello/:name",
|
|
||||||
}
|
|
||||||
for _, route := range routes {
|
|
||||||
recv := catchPanic(func() {
|
|
||||||
tree.addRoute(route, fakeHandler(route))
|
|
||||||
})
|
|
||||||
if recv != nil {
|
|
||||||
t.Fatalf("panic inserting route '%s': %v", route, recv)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//printChildren(tree, "")
|
|
||||||
|
|
||||||
tsrRoutes := [...]string{
|
|
||||||
"/hi/",
|
|
||||||
"/b",
|
|
||||||
"/search/gopher/",
|
|
||||||
"/cmd/vet",
|
|
||||||
"/src",
|
|
||||||
"/x/",
|
|
||||||
"/y",
|
|
||||||
"/0/go/",
|
|
||||||
"/1/go",
|
|
||||||
"/a",
|
|
||||||
"/doc/",
|
|
||||||
}
|
|
||||||
for _, route := range tsrRoutes {
|
|
||||||
handler, _, tsr := tree.getValue(route)
|
|
||||||
if handler != nil {
|
|
||||||
t.Fatalf("non-nil handler for TSR route '%s", route)
|
|
||||||
} else if !tsr {
|
|
||||||
t.Errorf("expected TSR recommendation for route '%s'", route)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
noTsrRoutes := [...]string{
|
|
||||||
"/",
|
|
||||||
"/no",
|
|
||||||
"/no/",
|
|
||||||
"/_",
|
|
||||||
"/_/",
|
|
||||||
"/api/world/abc",
|
|
||||||
}
|
|
||||||
for _, route := range noTsrRoutes {
|
|
||||||
handler, _, tsr := tree.getValue(route)
|
|
||||||
if handler != nil {
|
|
||||||
t.Fatalf("non-nil handler for No-TSR route '%s", route)
|
|
||||||
} else if tsr {
|
|
||||||
t.Errorf("expected no TSR recommendation for route '%s'", route)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTreeFindCaseInsensitivePath(t *testing.T) {
|
|
||||||
tree := &node{}
|
|
||||||
|
|
||||||
routes := [...]string{
|
|
||||||
"/hi",
|
|
||||||
"/b/",
|
|
||||||
"/ABC/",
|
|
||||||
"/search/:query",
|
|
||||||
"/cmd/:tool/",
|
|
||||||
"/src/*filepath",
|
|
||||||
"/x",
|
|
||||||
"/x/y",
|
|
||||||
"/y/",
|
|
||||||
"/y/z",
|
|
||||||
"/0/:id",
|
|
||||||
"/0/:id/1",
|
|
||||||
"/1/:id/",
|
|
||||||
"/1/:id/2",
|
|
||||||
"/aa",
|
|
||||||
"/a/",
|
|
||||||
"/doc",
|
|
||||||
"/doc/go_faq.html",
|
|
||||||
"/doc/go1.html",
|
|
||||||
"/doc/go/away",
|
|
||||||
"/no/a",
|
|
||||||
"/no/b",
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, route := range routes {
|
|
||||||
recv := catchPanic(func() {
|
|
||||||
tree.addRoute(route, fakeHandler(route))
|
|
||||||
})
|
|
||||||
if recv != nil {
|
|
||||||
t.Fatalf("panic inserting route '%s': %v", route, recv)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check out == in for all registered routes
|
|
||||||
// With fixTrailingSlash = true
|
|
||||||
for _, route := range routes {
|
|
||||||
out, found := tree.findCaseInsensitivePath(route, true)
|
|
||||||
if !found {
|
|
||||||
t.Errorf("Route '%s' not found!", route)
|
|
||||||
} else if string(out) != route {
|
|
||||||
t.Errorf("Wrong result for route '%s': %s", route, string(out))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// With fixTrailingSlash = false
|
|
||||||
for _, route := range routes {
|
|
||||||
out, found := tree.findCaseInsensitivePath(route, false)
|
|
||||||
if !found {
|
|
||||||
t.Errorf("Route '%s' not found!", route)
|
|
||||||
} else if string(out) != route {
|
|
||||||
t.Errorf("Wrong result for route '%s': %s", route, string(out))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tests := []struct {
|
|
||||||
in string
|
|
||||||
out string
|
|
||||||
found bool
|
|
||||||
slash bool
|
|
||||||
}{
|
|
||||||
{"/HI", "/hi", true, false},
|
|
||||||
{"/HI/", "/hi", true, true},
|
|
||||||
{"/B", "/b/", true, true},
|
|
||||||
{"/B/", "/b/", true, false},
|
|
||||||
{"/abc", "/ABC/", true, true},
|
|
||||||
{"/abc/", "/ABC/", true, false},
|
|
||||||
{"/aBc", "/ABC/", true, true},
|
|
||||||
{"/aBc/", "/ABC/", true, false},
|
|
||||||
{"/abC", "/ABC/", true, true},
|
|
||||||
{"/abC/", "/ABC/", true, false},
|
|
||||||
{"/SEARCH/QUERY", "/search/QUERY", true, false},
|
|
||||||
{"/SEARCH/QUERY/", "/search/QUERY", true, true},
|
|
||||||
{"/CMD/TOOL/", "/cmd/TOOL/", true, false},
|
|
||||||
{"/CMD/TOOL", "/cmd/TOOL/", true, true},
|
|
||||||
{"/SRC/FILE/PATH", "/src/FILE/PATH", true, false},
|
|
||||||
{"/x/Y", "/x/y", true, false},
|
|
||||||
{"/x/Y/", "/x/y", true, true},
|
|
||||||
{"/X/y", "/x/y", true, false},
|
|
||||||
{"/X/y/", "/x/y", true, true},
|
|
||||||
{"/X/Y", "/x/y", true, false},
|
|
||||||
{"/X/Y/", "/x/y", true, true},
|
|
||||||
{"/Y/", "/y/", true, false},
|
|
||||||
{"/Y", "/y/", true, true},
|
|
||||||
{"/Y/z", "/y/z", true, false},
|
|
||||||
{"/Y/z/", "/y/z", true, true},
|
|
||||||
{"/Y/Z", "/y/z", true, false},
|
|
||||||
{"/Y/Z/", "/y/z", true, true},
|
|
||||||
{"/y/Z", "/y/z", true, false},
|
|
||||||
{"/y/Z/", "/y/z", true, true},
|
|
||||||
{"/Aa", "/aa", true, false},
|
|
||||||
{"/Aa/", "/aa", true, true},
|
|
||||||
{"/AA", "/aa", true, false},
|
|
||||||
{"/AA/", "/aa", true, true},
|
|
||||||
{"/aA", "/aa", true, false},
|
|
||||||
{"/aA/", "/aa", true, true},
|
|
||||||
{"/A/", "/a/", true, false},
|
|
||||||
{"/A", "/a/", true, true},
|
|
||||||
{"/DOC", "/doc", true, false},
|
|
||||||
{"/DOC/", "/doc", true, true},
|
|
||||||
{"/NO", "", false, true},
|
|
||||||
{"/DOC/GO", "", false, true},
|
|
||||||
}
|
|
||||||
// With fixTrailingSlash = true
|
|
||||||
for _, test := range tests {
|
|
||||||
out, found := tree.findCaseInsensitivePath(test.in, true)
|
|
||||||
if found != test.found || (found && (string(out) != test.out)) {
|
|
||||||
t.Errorf("Wrong result for '%s': got %s, %t; want %s, %t",
|
|
||||||
test.in, string(out), found, test.out, test.found)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// With fixTrailingSlash = false
|
|
||||||
for _, test := range tests {
|
|
||||||
out, found := tree.findCaseInsensitivePath(test.in, false)
|
|
||||||
if test.slash {
|
|
||||||
if found { // test needs a trailingSlash fix. It must not be found!
|
|
||||||
t.Errorf("Found without fixTrailingSlash: %s; got %s", test.in, string(out))
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if found != test.found || (found && (string(out) != test.out)) {
|
|
||||||
t.Errorf("Wrong result for '%s': got %s, %t; want %s, %t",
|
|
||||||
test.in, string(out), found, test.out, test.found)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTreeInvalidNodeType(t *testing.T) {
|
|
||||||
const panicMsg = "invalid node type"
|
|
||||||
|
|
||||||
tree := &node{}
|
|
||||||
tree.addRoute("/", fakeHandler("/"))
|
|
||||||
tree.addRoute("/:page", fakeHandler("/:page"))
|
|
||||||
|
|
||||||
// set invalid node type
|
|
||||||
tree.children[0].nType = 42
|
|
||||||
|
|
||||||
// normal lookup
|
|
||||||
recv := catchPanic(func() {
|
|
||||||
tree.getValue("/test")
|
|
||||||
})
|
|
||||||
if rs, ok := recv.(string); !ok || rs != panicMsg {
|
|
||||||
t.Fatalf("Expected panic '"+panicMsg+"', got '%v'", recv)
|
|
||||||
}
|
|
||||||
|
|
||||||
// case-insensitive lookup
|
|
||||||
recv = catchPanic(func() {
|
|
||||||
tree.findCaseInsensitivePath("/test", true)
|
|
||||||
})
|
|
||||||
if rs, ok := recv.(string); !ok || rs != panicMsg {
|
|
||||||
t.Fatalf("Expected panic '"+panicMsg+"', got '%v'", recv)
|
|
||||||
}
|
|
||||||
}
|
|
120
Godeps/_workspace/src/github.com/kylelemons/godebug/diff/diff_test.go
generated
vendored
120
Godeps/_workspace/src/github.com/kylelemons/godebug/diff/diff_test.go
generated
vendored
|
@ -1,120 +0,0 @@
|
||||||
// Copyright 2013 Google Inc. All rights reserved.
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
package diff
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"reflect"
|
|
||||||
"strings"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestDiff(t *testing.T) {
|
|
||||||
tests := []struct {
|
|
||||||
desc string
|
|
||||||
A, B []string
|
|
||||||
chunks []Chunk
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
desc: "constitution",
|
|
||||||
A: []string{
|
|
||||||
"We the People of the United States, in Order to form a more perfect Union,",
|
|
||||||
"establish Justice, insure domestic Tranquility, provide for the common defence,",
|
|
||||||
"and secure the Blessings of Liberty to ourselves",
|
|
||||||
"and our Posterity, do ordain and establish this Constitution for the United",
|
|
||||||
"States of America.",
|
|
||||||
},
|
|
||||||
B: []string{
|
|
||||||
"We the People of the United States, in Order to form a more perfect Union,",
|
|
||||||
"establish Justice, insure domestic Tranquility, provide for the common defence,",
|
|
||||||
"promote the general Welfare, and secure the Blessings of Liberty to ourselves",
|
|
||||||
"and our Posterity, do ordain and establish this Constitution for the United",
|
|
||||||
"States of America.",
|
|
||||||
},
|
|
||||||
chunks: []Chunk{
|
|
||||||
0: {
|
|
||||||
Equal: []string{
|
|
||||||
"We the People of the United States, in Order to form a more perfect Union,",
|
|
||||||
"establish Justice, insure domestic Tranquility, provide for the common defence,",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
1: {
|
|
||||||
Deleted: []string{
|
|
||||||
"and secure the Blessings of Liberty to ourselves",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
2: {
|
|
||||||
Added: []string{
|
|
||||||
"promote the general Welfare, and secure the Blessings of Liberty to ourselves",
|
|
||||||
},
|
|
||||||
Equal: []string{
|
|
||||||
"and our Posterity, do ordain and establish this Constitution for the United",
|
|
||||||
"States of America.",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, test := range tests {
|
|
||||||
got := DiffChunks(test.A, test.B)
|
|
||||||
if got, want := len(got), len(test.chunks); got != want {
|
|
||||||
t.Errorf("%s: edit distance = %v, want %v", test.desc, got-1, want-1)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
for i := range got {
|
|
||||||
got, want := got[i], test.chunks[i]
|
|
||||||
if got, want := got.Added, want.Added; !reflect.DeepEqual(got, want) {
|
|
||||||
t.Errorf("%s[%d]: Added = %v, want %v", test.desc, i, got, want)
|
|
||||||
}
|
|
||||||
if got, want := got.Deleted, want.Deleted; !reflect.DeepEqual(got, want) {
|
|
||||||
t.Errorf("%s[%d]: Deleted = %v, want %v", test.desc, i, got, want)
|
|
||||||
}
|
|
||||||
if got, want := got.Equal, want.Equal; !reflect.DeepEqual(got, want) {
|
|
||||||
t.Errorf("%s[%d]: Equal = %v, want %v", test.desc, i, got, want)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func ExampleDiff() {
|
|
||||||
constitution := strings.TrimSpace(`
|
|
||||||
We the People of the United States, in Order to form a more perfect Union,
|
|
||||||
establish Justice, insure domestic Tranquility, provide for the common defence,
|
|
||||||
promote the general Welfare, and secure the Blessings of Liberty to ourselves
|
|
||||||
and our Posterity, do ordain and establish this Constitution for the United
|
|
||||||
States of America.
|
|
||||||
`)
|
|
||||||
|
|
||||||
got := strings.TrimSpace(`
|
|
||||||
:wq
|
|
||||||
We the People of the United States, in Order to form a more perfect Union,
|
|
||||||
establish Justice, insure domestic Tranquility, provide for the common defence,
|
|
||||||
and secure the Blessings of Liberty to ourselves
|
|
||||||
and our Posterity, do ordain and establish this Constitution for the United
|
|
||||||
States of America.
|
|
||||||
`)
|
|
||||||
|
|
||||||
fmt.Println(Diff(got, constitution))
|
|
||||||
|
|
||||||
// Output:
|
|
||||||
// -:wq
|
|
||||||
// We the People of the United States, in Order to form a more perfect Union,
|
|
||||||
// establish Justice, insure domestic Tranquility, provide for the common defence,
|
|
||||||
// -and secure the Blessings of Liberty to ourselves
|
|
||||||
// +promote the general Welfare, and secure the Blessings of Liberty to ourselves
|
|
||||||
// and our Posterity, do ordain and establish this Constitution for the United
|
|
||||||
// States of America.
|
|
||||||
}
|
|
158
Godeps/_workspace/src/github.com/kylelemons/godebug/pretty/examples_test.go
generated
vendored
158
Godeps/_workspace/src/github.com/kylelemons/godebug/pretty/examples_test.go
generated
vendored
|
@ -1,158 +0,0 @@
|
||||||
// Copyright 2013 Google Inc. All rights reserved.
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
package pretty_test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"github.com/kylelemons/godebug/pretty"
|
|
||||||
)
|
|
||||||
|
|
||||||
func ExampleConfig_Sprint() {
|
|
||||||
type Pair [2]int
|
|
||||||
type Map struct {
|
|
||||||
Name string
|
|
||||||
Players map[string]Pair
|
|
||||||
Obstacles map[Pair]string
|
|
||||||
}
|
|
||||||
|
|
||||||
m := Map{
|
|
||||||
Name: "Rock Creek",
|
|
||||||
Players: map[string]Pair{
|
|
||||||
"player1": {1, 3},
|
|
||||||
"player2": {0, -1},
|
|
||||||
},
|
|
||||||
Obstacles: map[Pair]string{
|
|
||||||
Pair{0, 0}: "rock",
|
|
||||||
Pair{2, 1}: "pond",
|
|
||||||
Pair{1, 1}: "stream",
|
|
||||||
Pair{0, 1}: "stream",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
// Specific output formats
|
|
||||||
compact := &pretty.Config{
|
|
||||||
Compact: true,
|
|
||||||
}
|
|
||||||
diffable := &pretty.Config{
|
|
||||||
Diffable: true,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Print out a summary
|
|
||||||
fmt.Printf("Players: %s\n", compact.Sprint(m.Players))
|
|
||||||
|
|
||||||
// Print diffable output
|
|
||||||
fmt.Printf("Map State:\n%s", diffable.Sprint(m))
|
|
||||||
|
|
||||||
// Output:
|
|
||||||
// Players: {player1:[1,3],player2:[0,-1]}
|
|
||||||
// Map State:
|
|
||||||
// {
|
|
||||||
// Name: "Rock Creek",
|
|
||||||
// Players: {
|
|
||||||
// player1: [
|
|
||||||
// 1,
|
|
||||||
// 3,
|
|
||||||
// ],
|
|
||||||
// player2: [
|
|
||||||
// 0,
|
|
||||||
// -1,
|
|
||||||
// ],
|
|
||||||
// },
|
|
||||||
// Obstacles: {
|
|
||||||
// [0,0]: "rock",
|
|
||||||
// [0,1]: "stream",
|
|
||||||
// [1,1]: "stream",
|
|
||||||
// [2,1]: "pond",
|
|
||||||
// },
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
func ExamplePrint() {
|
|
||||||
type ShipManifest struct {
|
|
||||||
Name string
|
|
||||||
Crew map[string]string
|
|
||||||
Androids int
|
|
||||||
Stolen bool
|
|
||||||
}
|
|
||||||
|
|
||||||
manifest := &ShipManifest{
|
|
||||||
Name: "Spaceship Heart of Gold",
|
|
||||||
Crew: map[string]string{
|
|
||||||
"Zaphod Beeblebrox": "Galactic President",
|
|
||||||
"Trillian": "Human",
|
|
||||||
"Ford Prefect": "A Hoopy Frood",
|
|
||||||
"Arthur Dent": "Along for the Ride",
|
|
||||||
},
|
|
||||||
Androids: 1,
|
|
||||||
Stolen: true,
|
|
||||||
}
|
|
||||||
|
|
||||||
pretty.Print(manifest)
|
|
||||||
|
|
||||||
// Output:
|
|
||||||
// {Name: "Spaceship Heart of Gold",
|
|
||||||
// Crew: {Arthur Dent: "Along for the Ride",
|
|
||||||
// Ford Prefect: "A Hoopy Frood",
|
|
||||||
// Trillian: "Human",
|
|
||||||
// Zaphod Beeblebrox: "Galactic President"},
|
|
||||||
// Androids: 1,
|
|
||||||
// Stolen: true}
|
|
||||||
}
|
|
||||||
|
|
||||||
func ExampleCompare() {
|
|
||||||
type ShipManifest struct {
|
|
||||||
Name string
|
|
||||||
Crew map[string]string
|
|
||||||
Androids int
|
|
||||||
Stolen bool
|
|
||||||
}
|
|
||||||
|
|
||||||
reported := &ShipManifest{
|
|
||||||
Name: "Spaceship Heart of Gold",
|
|
||||||
Crew: map[string]string{
|
|
||||||
"Zaphod Beeblebrox": "Galactic President",
|
|
||||||
"Trillian": "Human",
|
|
||||||
"Ford Prefect": "A Hoopy Frood",
|
|
||||||
"Arthur Dent": "Along for the Ride",
|
|
||||||
},
|
|
||||||
Androids: 1,
|
|
||||||
Stolen: true,
|
|
||||||
}
|
|
||||||
|
|
||||||
expected := &ShipManifest{
|
|
||||||
Name: "Spaceship Heart of Gold",
|
|
||||||
Crew: map[string]string{
|
|
||||||
"Rowan Artosok": "Captain",
|
|
||||||
},
|
|
||||||
Androids: 1,
|
|
||||||
Stolen: false,
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Println(pretty.Compare(reported, expected))
|
|
||||||
// Output:
|
|
||||||
// {
|
|
||||||
// Name: "Spaceship Heart of Gold",
|
|
||||||
// Crew: {
|
|
||||||
// - Arthur Dent: "Along for the Ride",
|
|
||||||
// - Ford Prefect: "A Hoopy Frood",
|
|
||||||
// - Trillian: "Human",
|
|
||||||
// - Zaphod Beeblebrox: "Galactic President",
|
|
||||||
// + Rowan Artosok: "Captain",
|
|
||||||
// },
|
|
||||||
// Androids: 1,
|
|
||||||
// - Stolen: true,
|
|
||||||
// + Stolen: false,
|
|
||||||
// }
|
|
||||||
}
|
|
72
Godeps/_workspace/src/github.com/kylelemons/godebug/pretty/public_test.go
generated
vendored
72
Godeps/_workspace/src/github.com/kylelemons/godebug/pretty/public_test.go
generated
vendored
|
@ -1,72 +0,0 @@
|
||||||
// Copyright 2013 Google Inc. All rights reserved.
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
package pretty
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestDiff(t *testing.T) {
|
|
||||||
type example struct {
|
|
||||||
Name string
|
|
||||||
Age int
|
|
||||||
Friends []string
|
|
||||||
}
|
|
||||||
|
|
||||||
tests := []struct {
|
|
||||||
desc string
|
|
||||||
got, want interface{}
|
|
||||||
diff string
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
desc: "basic struct",
|
|
||||||
got: example{
|
|
||||||
Name: "Zaphd",
|
|
||||||
Age: 42,
|
|
||||||
Friends: []string{
|
|
||||||
"Ford Prefect",
|
|
||||||
"Trillian",
|
|
||||||
"Marvin",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
want: example{
|
|
||||||
Name: "Zaphod",
|
|
||||||
Age: 42,
|
|
||||||
Friends: []string{
|
|
||||||
"Ford Prefect",
|
|
||||||
"Trillian",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
diff: ` {
|
|
||||||
- Name: "Zaphd",
|
|
||||||
+ Name: "Zaphod",
|
|
||||||
Age: 42,
|
|
||||||
Friends: [
|
|
||||||
"Ford Prefect",
|
|
||||||
"Trillian",
|
|
||||||
- "Marvin",
|
|
||||||
],
|
|
||||||
}`,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, test := range tests {
|
|
||||||
if got, want := Compare(test.got, test.want), test.diff; got != want {
|
|
||||||
t.Errorf("%s:", test.desc)
|
|
||||||
t.Errorf(" got: %q", got)
|
|
||||||
t.Errorf(" want: %q", want)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
143
Godeps/_workspace/src/github.com/kylelemons/godebug/pretty/reflect_test.go
generated
vendored
143
Godeps/_workspace/src/github.com/kylelemons/godebug/pretty/reflect_test.go
generated
vendored
|
@ -1,143 +0,0 @@
|
||||||
// Copyright 2013 Google Inc. All rights reserved.
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
package pretty
|
|
||||||
|
|
||||||
import (
|
|
||||||
"reflect"
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestVal2nodeDefault(t *testing.T) {
|
|
||||||
tests := []struct {
|
|
||||||
desc string
|
|
||||||
raw interface{}
|
|
||||||
want node
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
"nil",
|
|
||||||
(*int)(nil),
|
|
||||||
rawVal("nil"),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"string",
|
|
||||||
"zaphod",
|
|
||||||
stringVal("zaphod"),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"slice",
|
|
||||||
[]string{"a", "b"},
|
|
||||||
list{stringVal("a"), stringVal("b")},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"map",
|
|
||||||
map[string]string{
|
|
||||||
"zaphod": "beeblebrox",
|
|
||||||
"ford": "prefect",
|
|
||||||
},
|
|
||||||
keyvals{
|
|
||||||
{"ford", stringVal("prefect")},
|
|
||||||
{"zaphod", stringVal("beeblebrox")},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"map of [2]int",
|
|
||||||
map[[2]int]string{
|
|
||||||
[2]int{-1, 2}: "school",
|
|
||||||
[2]int{0, 0}: "origin",
|
|
||||||
[2]int{1, 3}: "home",
|
|
||||||
},
|
|
||||||
keyvals{
|
|
||||||
{"[-1,2]", stringVal("school")},
|
|
||||||
{"[0,0]", stringVal("origin")},
|
|
||||||
{"[1,3]", stringVal("home")},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"struct",
|
|
||||||
struct{ Zaphod, Ford string }{"beeblebrox", "prefect"},
|
|
||||||
keyvals{
|
|
||||||
{"Zaphod", stringVal("beeblebrox")},
|
|
||||||
{"Ford", stringVal("prefect")},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"int",
|
|
||||||
3,
|
|
||||||
rawVal("3"),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, test := range tests {
|
|
||||||
if got, want := DefaultConfig.val2node(reflect.ValueOf(test.raw)), test.want; !reflect.DeepEqual(got, want) {
|
|
||||||
t.Errorf("%s: got %#v, want %#v", test.desc, got, want)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestVal2node(t *testing.T) {
|
|
||||||
tests := []struct {
|
|
||||||
desc string
|
|
||||||
raw interface{}
|
|
||||||
cfg *Config
|
|
||||||
want node
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
"struct default",
|
|
||||||
struct{ Zaphod, Ford, foo string }{"beeblebrox", "prefect", "BAD"},
|
|
||||||
DefaultConfig,
|
|
||||||
keyvals{
|
|
||||||
{"Zaphod", stringVal("beeblebrox")},
|
|
||||||
{"Ford", stringVal("prefect")},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"struct w/ IncludeUnexported",
|
|
||||||
struct{ Zaphod, Ford, foo string }{"beeblebrox", "prefect", "GOOD"},
|
|
||||||
&Config{
|
|
||||||
IncludeUnexported: true,
|
|
||||||
},
|
|
||||||
keyvals{
|
|
||||||
{"Zaphod", stringVal("beeblebrox")},
|
|
||||||
{"Ford", stringVal("prefect")},
|
|
||||||
{"foo", stringVal("GOOD")},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"time default",
|
|
||||||
struct{ Date time.Time }{time.Unix(1234567890, 0).UTC()},
|
|
||||||
DefaultConfig,
|
|
||||||
keyvals{
|
|
||||||
{"Date", keyvals{}}, // empty struct, it has unexported fields
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"time w/ PrintStringers",
|
|
||||||
struct{ Date time.Time }{time.Unix(1234567890, 0).UTC()},
|
|
||||||
&Config{
|
|
||||||
PrintStringers: true,
|
|
||||||
},
|
|
||||||
keyvals{
|
|
||||||
{"Date", stringVal("2009-02-13 23:31:30 +0000 UTC")},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, test := range tests {
|
|
||||||
if got, want := test.cfg.val2node(reflect.ValueOf(test.raw)), test.want; !reflect.DeepEqual(got, want) {
|
|
||||||
t.Errorf("%s: got %#v, want %#v", test.desc, got, want)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
262
Godeps/_workspace/src/github.com/kylelemons/godebug/pretty/structure_test.go
generated
vendored
262
Godeps/_workspace/src/github.com/kylelemons/godebug/pretty/structure_test.go
generated
vendored
|
@ -1,262 +0,0 @@
|
||||||
// Copyright 2013 Google Inc. All rights reserved.
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
package pretty
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestWriteTo(t *testing.T) {
|
|
||||||
tests := []struct {
|
|
||||||
desc string
|
|
||||||
node node
|
|
||||||
normal string
|
|
||||||
extended string
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
desc: "string",
|
|
||||||
node: stringVal("zaphod"),
|
|
||||||
normal: `"zaphod"`,
|
|
||||||
extended: `"zaphod"`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
desc: "raw",
|
|
||||||
node: rawVal("42"),
|
|
||||||
normal: `42`,
|
|
||||||
extended: `42`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
desc: "keyvals",
|
|
||||||
node: keyvals{
|
|
||||||
{"name", stringVal("zaphod")},
|
|
||||||
{"age", rawVal("42")},
|
|
||||||
},
|
|
||||||
normal: `{name: "zaphod",
|
|
||||||
age: 42}`,
|
|
||||||
extended: `{
|
|
||||||
name: "zaphod",
|
|
||||||
age: 42,
|
|
||||||
}`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
desc: "list",
|
|
||||||
node: list{
|
|
||||||
stringVal("zaphod"),
|
|
||||||
rawVal("42"),
|
|
||||||
},
|
|
||||||
normal: `["zaphod",
|
|
||||||
42]`,
|
|
||||||
extended: `[
|
|
||||||
"zaphod",
|
|
||||||
42,
|
|
||||||
]`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
desc: "nested",
|
|
||||||
node: list{
|
|
||||||
stringVal("first"),
|
|
||||||
list{rawVal("1"), rawVal("2"), rawVal("3")},
|
|
||||||
keyvals{
|
|
||||||
{"trillian", keyvals{
|
|
||||||
{"race", stringVal("human")},
|
|
||||||
{"age", rawVal("36")},
|
|
||||||
}},
|
|
||||||
{"zaphod", keyvals{
|
|
||||||
{"occupation", stringVal("president of the galaxy")},
|
|
||||||
{"features", stringVal("two heads")},
|
|
||||||
}},
|
|
||||||
},
|
|
||||||
keyvals{},
|
|
||||||
},
|
|
||||||
normal: `["first",
|
|
||||||
[1,
|
|
||||||
2,
|
|
||||||
3],
|
|
||||||
{trillian: {race: "human",
|
|
||||||
age: 36},
|
|
||||||
zaphod: {occupation: "president of the galaxy",
|
|
||||||
features: "two heads"}},
|
|
||||||
{}]`,
|
|
||||||
extended: `[
|
|
||||||
"first",
|
|
||||||
[
|
|
||||||
1,
|
|
||||||
2,
|
|
||||||
3,
|
|
||||||
],
|
|
||||||
{
|
|
||||||
trillian: {
|
|
||||||
race: "human",
|
|
||||||
age: 36,
|
|
||||||
},
|
|
||||||
zaphod: {
|
|
||||||
occupation: "president of the galaxy",
|
|
||||||
features: "two heads",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{},
|
|
||||||
]`,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, test := range tests {
|
|
||||||
buf := new(bytes.Buffer)
|
|
||||||
test.node.WriteTo(buf, "", &Config{})
|
|
||||||
if got, want := buf.String(), test.normal; got != want {
|
|
||||||
t.Errorf("%s: normal rendendered incorrectly\ngot:\n%s\nwant:\n%s", test.desc, got, want)
|
|
||||||
}
|
|
||||||
buf.Reset()
|
|
||||||
test.node.WriteTo(buf, "", &Config{Diffable: true})
|
|
||||||
if got, want := buf.String(), test.extended; got != want {
|
|
||||||
t.Errorf("%s: extended rendendered incorrectly\ngot:\n%s\nwant:\n%s", test.desc, got, want)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCompactString(t *testing.T) {
|
|
||||||
tests := []struct {
|
|
||||||
node
|
|
||||||
compact string
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
stringVal("abc"),
|
|
||||||
"abc",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
rawVal("2"),
|
|
||||||
"2",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
list{
|
|
||||||
rawVal("2"),
|
|
||||||
rawVal("3"),
|
|
||||||
},
|
|
||||||
"[2,3]",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
keyvals{
|
|
||||||
{"name", stringVal("zaphod")},
|
|
||||||
{"age", rawVal("42")},
|
|
||||||
},
|
|
||||||
`{name:"zaphod",age:42}`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
list{
|
|
||||||
list{
|
|
||||||
rawVal("0"),
|
|
||||||
rawVal("1"),
|
|
||||||
rawVal("2"),
|
|
||||||
rawVal("3"),
|
|
||||||
},
|
|
||||||
list{
|
|
||||||
rawVal("1"),
|
|
||||||
rawVal("2"),
|
|
||||||
rawVal("3"),
|
|
||||||
rawVal("0"),
|
|
||||||
},
|
|
||||||
list{
|
|
||||||
rawVal("2"),
|
|
||||||
rawVal("3"),
|
|
||||||
rawVal("0"),
|
|
||||||
rawVal("1"),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
`[[0,1,2,3],[1,2,3,0],[2,3,0,1]]`,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, test := range tests {
|
|
||||||
if got, want := compactString(test.node), test.compact; got != want {
|
|
||||||
t.Errorf("%#v: compact = %q, want %q", test.node, got, want)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestShortList(t *testing.T) {
|
|
||||||
cfg := &Config{
|
|
||||||
ShortList: 16,
|
|
||||||
}
|
|
||||||
|
|
||||||
tests := []struct {
|
|
||||||
node
|
|
||||||
want string
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
list{
|
|
||||||
list{
|
|
||||||
rawVal("0"),
|
|
||||||
rawVal("1"),
|
|
||||||
rawVal("2"),
|
|
||||||
rawVal("3"),
|
|
||||||
},
|
|
||||||
list{
|
|
||||||
rawVal("1"),
|
|
||||||
rawVal("2"),
|
|
||||||
rawVal("3"),
|
|
||||||
rawVal("0"),
|
|
||||||
},
|
|
||||||
list{
|
|
||||||
rawVal("2"),
|
|
||||||
rawVal("3"),
|
|
||||||
rawVal("0"),
|
|
||||||
rawVal("1"),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
`[[0,1,2,3],
|
|
||||||
[1,2,3,0],
|
|
||||||
[2,3,0,1]]`,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, test := range tests {
|
|
||||||
buf := new(bytes.Buffer)
|
|
||||||
test.node.WriteTo(buf, "", cfg)
|
|
||||||
if got, want := buf.String(), test.want; got != want {
|
|
||||||
t.Errorf("%#v: got:\n%s\nwant:\n%s", test.node, got, want)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var benchNode = keyvals{
|
|
||||||
{"list", list{
|
|
||||||
rawVal("0"),
|
|
||||||
rawVal("1"),
|
|
||||||
rawVal("2"),
|
|
||||||
rawVal("3"),
|
|
||||||
}},
|
|
||||||
{"keyvals", keyvals{
|
|
||||||
{"a", stringVal("b")},
|
|
||||||
{"c", stringVal("e")},
|
|
||||||
{"d", stringVal("f")},
|
|
||||||
}},
|
|
||||||
}
|
|
||||||
|
|
||||||
func benchOpts(b *testing.B, cfg *Config) {
|
|
||||||
buf := new(bytes.Buffer)
|
|
||||||
benchNode.WriteTo(buf, "", cfg)
|
|
||||||
b.SetBytes(int64(buf.Len()))
|
|
||||||
b.ResetTimer()
|
|
||||||
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
buf.Reset()
|
|
||||||
benchNode.WriteTo(buf, "", cfg)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkWriteDefault(b *testing.B) { benchOpts(b, DefaultConfig) }
|
|
||||||
func BenchmarkWriteShortList(b *testing.B) { benchOpts(b, &Config{ShortList: 16}) }
|
|
||||||
func BenchmarkWriteCompact(b *testing.B) { benchOpts(b, &Config{Compact: true}) }
|
|
||||||
func BenchmarkWriteDiffable(b *testing.B) { benchOpts(b, &Config{Diffable: true}) }
|
|
436
Godeps/_workspace/src/github.com/lib/pq/bench_test.go
generated
vendored
436
Godeps/_workspace/src/github.com/lib/pq/bench_test.go
generated
vendored
|
@ -1,436 +0,0 @@
|
||||||
// +build go1.1
|
|
||||||
|
|
||||||
package pq
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bufio"
|
|
||||||
"bytes"
|
|
||||||
"database/sql"
|
|
||||||
"database/sql/driver"
|
|
||||||
"github.com/lib/pq/oid"
|
|
||||||
"io"
|
|
||||||
"math/rand"
|
|
||||||
"net"
|
|
||||||
"runtime"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
"sync"
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
selectStringQuery = "SELECT '" + strings.Repeat("0123456789", 10) + "'"
|
|
||||||
selectSeriesQuery = "SELECT generate_series(1, 100)"
|
|
||||||
)
|
|
||||||
|
|
||||||
func BenchmarkSelectString(b *testing.B) {
|
|
||||||
var result string
|
|
||||||
benchQuery(b, selectStringQuery, &result)
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkSelectSeries(b *testing.B) {
|
|
||||||
var result int
|
|
||||||
benchQuery(b, selectSeriesQuery, &result)
|
|
||||||
}
|
|
||||||
|
|
||||||
func benchQuery(b *testing.B, query string, result interface{}) {
|
|
||||||
b.Skip("current pq database-backed benchmarks are inconsistent")
|
|
||||||
b.StopTimer()
|
|
||||||
db := openTestConn(b)
|
|
||||||
defer db.Close()
|
|
||||||
b.StartTimer()
|
|
||||||
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
benchQueryLoop(b, db, query, result)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func benchQueryLoop(b *testing.B, db *sql.DB, query string, result interface{}) {
|
|
||||||
rows, err := db.Query(query)
|
|
||||||
if err != nil {
|
|
||||||
b.Fatal(err)
|
|
||||||
}
|
|
||||||
defer rows.Close()
|
|
||||||
for rows.Next() {
|
|
||||||
err = rows.Scan(result)
|
|
||||||
if err != nil {
|
|
||||||
b.Fatal("failed to scan", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// reading from circularConn yields content[:prefixLen] once, followed by
|
|
||||||
// content[prefixLen:] over and over again. It never returns EOF.
|
|
||||||
type circularConn struct {
|
|
||||||
content string
|
|
||||||
prefixLen int
|
|
||||||
pos int
|
|
||||||
net.Conn // for all other net.Conn methods that will never be called
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *circularConn) Read(b []byte) (n int, err error) {
|
|
||||||
n = copy(b, r.content[r.pos:])
|
|
||||||
r.pos += n
|
|
||||||
if r.pos >= len(r.content) {
|
|
||||||
r.pos = r.prefixLen
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *circularConn) Write(b []byte) (n int, err error) { return len(b), nil }
|
|
||||||
|
|
||||||
func (r *circularConn) Close() error { return nil }
|
|
||||||
|
|
||||||
func fakeConn(content string, prefixLen int) *conn {
|
|
||||||
c := &circularConn{content: content, prefixLen: prefixLen}
|
|
||||||
return &conn{buf: bufio.NewReader(c), c: c}
|
|
||||||
}
|
|
||||||
|
|
||||||
// This benchmark is meant to be the same as BenchmarkSelectString, but takes
|
|
||||||
// out some of the factors this package can't control. The numbers are less noisy,
|
|
||||||
// but also the costs of network communication aren't accurately represented.
|
|
||||||
func BenchmarkMockSelectString(b *testing.B) {
|
|
||||||
b.StopTimer()
|
|
||||||
// taken from a recorded run of BenchmarkSelectString
|
|
||||||
// See: http://www.postgresql.org/docs/current/static/protocol-message-formats.html
|
|
||||||
const response = "1\x00\x00\x00\x04" +
|
|
||||||
"t\x00\x00\x00\x06\x00\x00" +
|
|
||||||
"T\x00\x00\x00!\x00\x01?column?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\xc1\xff\xfe\xff\xff\xff\xff\x00\x00" +
|
|
||||||
"Z\x00\x00\x00\x05I" +
|
|
||||||
"2\x00\x00\x00\x04" +
|
|
||||||
"D\x00\x00\x00n\x00\x01\x00\x00\x00d0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789" +
|
|
||||||
"C\x00\x00\x00\rSELECT 1\x00" +
|
|
||||||
"Z\x00\x00\x00\x05I" +
|
|
||||||
"3\x00\x00\x00\x04" +
|
|
||||||
"Z\x00\x00\x00\x05I"
|
|
||||||
c := fakeConn(response, 0)
|
|
||||||
b.StartTimer()
|
|
||||||
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
benchMockQuery(b, c, selectStringQuery)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var seriesRowData = func() string {
|
|
||||||
var buf bytes.Buffer
|
|
||||||
for i := 1; i <= 100; i++ {
|
|
||||||
digits := byte(2)
|
|
||||||
if i >= 100 {
|
|
||||||
digits = 3
|
|
||||||
} else if i < 10 {
|
|
||||||
digits = 1
|
|
||||||
}
|
|
||||||
buf.WriteString("D\x00\x00\x00")
|
|
||||||
buf.WriteByte(10 + digits)
|
|
||||||
buf.WriteString("\x00\x01\x00\x00\x00")
|
|
||||||
buf.WriteByte(digits)
|
|
||||||
buf.WriteString(strconv.Itoa(i))
|
|
||||||
}
|
|
||||||
return buf.String()
|
|
||||||
}()
|
|
||||||
|
|
||||||
func BenchmarkMockSelectSeries(b *testing.B) {
|
|
||||||
b.StopTimer()
|
|
||||||
var response = "1\x00\x00\x00\x04" +
|
|
||||||
"t\x00\x00\x00\x06\x00\x00" +
|
|
||||||
"T\x00\x00\x00!\x00\x01?column?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\xc1\xff\xfe\xff\xff\xff\xff\x00\x00" +
|
|
||||||
"Z\x00\x00\x00\x05I" +
|
|
||||||
"2\x00\x00\x00\x04" +
|
|
||||||
seriesRowData +
|
|
||||||
"C\x00\x00\x00\x0fSELECT 100\x00" +
|
|
||||||
"Z\x00\x00\x00\x05I" +
|
|
||||||
"3\x00\x00\x00\x04" +
|
|
||||||
"Z\x00\x00\x00\x05I"
|
|
||||||
c := fakeConn(response, 0)
|
|
||||||
b.StartTimer()
|
|
||||||
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
benchMockQuery(b, c, selectSeriesQuery)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func benchMockQuery(b *testing.B, c *conn, query string) {
|
|
||||||
stmt, err := c.Prepare(query)
|
|
||||||
if err != nil {
|
|
||||||
b.Fatal(err)
|
|
||||||
}
|
|
||||||
defer stmt.Close()
|
|
||||||
rows, err := stmt.Query(nil)
|
|
||||||
if err != nil {
|
|
||||||
b.Fatal(err)
|
|
||||||
}
|
|
||||||
defer rows.Close()
|
|
||||||
var dest [1]driver.Value
|
|
||||||
for {
|
|
||||||
if err := rows.Next(dest[:]); err != nil {
|
|
||||||
if err == io.EOF {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
b.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkPreparedSelectString(b *testing.B) {
|
|
||||||
var result string
|
|
||||||
benchPreparedQuery(b, selectStringQuery, &result)
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkPreparedSelectSeries(b *testing.B) {
|
|
||||||
var result int
|
|
||||||
benchPreparedQuery(b, selectSeriesQuery, &result)
|
|
||||||
}
|
|
||||||
|
|
||||||
func benchPreparedQuery(b *testing.B, query string, result interface{}) {
|
|
||||||
b.Skip("current pq database-backed benchmarks are inconsistent")
|
|
||||||
b.StopTimer()
|
|
||||||
db := openTestConn(b)
|
|
||||||
defer db.Close()
|
|
||||||
stmt, err := db.Prepare(query)
|
|
||||||
if err != nil {
|
|
||||||
b.Fatal(err)
|
|
||||||
}
|
|
||||||
defer stmt.Close()
|
|
||||||
b.StartTimer()
|
|
||||||
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
benchPreparedQueryLoop(b, db, stmt, result)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func benchPreparedQueryLoop(b *testing.B, db *sql.DB, stmt *sql.Stmt, result interface{}) {
|
|
||||||
rows, err := stmt.Query()
|
|
||||||
if err != nil {
|
|
||||||
b.Fatal(err)
|
|
||||||
}
|
|
||||||
if !rows.Next() {
|
|
||||||
rows.Close()
|
|
||||||
b.Fatal("no rows")
|
|
||||||
}
|
|
||||||
defer rows.Close()
|
|
||||||
for rows.Next() {
|
|
||||||
err = rows.Scan(&result)
|
|
||||||
if err != nil {
|
|
||||||
b.Fatal("failed to scan")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// See the comment for BenchmarkMockSelectString.
|
|
||||||
func BenchmarkMockPreparedSelectString(b *testing.B) {
|
|
||||||
b.StopTimer()
|
|
||||||
const parseResponse = "1\x00\x00\x00\x04" +
|
|
||||||
"t\x00\x00\x00\x06\x00\x00" +
|
|
||||||
"T\x00\x00\x00!\x00\x01?column?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\xc1\xff\xfe\xff\xff\xff\xff\x00\x00" +
|
|
||||||
"Z\x00\x00\x00\x05I"
|
|
||||||
const responses = parseResponse +
|
|
||||||
"2\x00\x00\x00\x04" +
|
|
||||||
"D\x00\x00\x00n\x00\x01\x00\x00\x00d0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789" +
|
|
||||||
"C\x00\x00\x00\rSELECT 1\x00" +
|
|
||||||
"Z\x00\x00\x00\x05I"
|
|
||||||
c := fakeConn(responses, len(parseResponse))
|
|
||||||
|
|
||||||
stmt, err := c.Prepare(selectStringQuery)
|
|
||||||
if err != nil {
|
|
||||||
b.Fatal(err)
|
|
||||||
}
|
|
||||||
b.StartTimer()
|
|
||||||
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
benchPreparedMockQuery(b, c, stmt)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkMockPreparedSelectSeries(b *testing.B) {
|
|
||||||
b.StopTimer()
|
|
||||||
const parseResponse = "1\x00\x00\x00\x04" +
|
|
||||||
"t\x00\x00\x00\x06\x00\x00" +
|
|
||||||
"T\x00\x00\x00!\x00\x01?column?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\xc1\xff\xfe\xff\xff\xff\xff\x00\x00" +
|
|
||||||
"Z\x00\x00\x00\x05I"
|
|
||||||
var responses = parseResponse +
|
|
||||||
"2\x00\x00\x00\x04" +
|
|
||||||
seriesRowData +
|
|
||||||
"C\x00\x00\x00\x0fSELECT 100\x00" +
|
|
||||||
"Z\x00\x00\x00\x05I"
|
|
||||||
c := fakeConn(responses, len(parseResponse))
|
|
||||||
|
|
||||||
stmt, err := c.Prepare(selectSeriesQuery)
|
|
||||||
if err != nil {
|
|
||||||
b.Fatal(err)
|
|
||||||
}
|
|
||||||
b.StartTimer()
|
|
||||||
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
benchPreparedMockQuery(b, c, stmt)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func benchPreparedMockQuery(b *testing.B, c *conn, stmt driver.Stmt) {
|
|
||||||
rows, err := stmt.Query(nil)
|
|
||||||
if err != nil {
|
|
||||||
b.Fatal(err)
|
|
||||||
}
|
|
||||||
defer rows.Close()
|
|
||||||
var dest [1]driver.Value
|
|
||||||
for {
|
|
||||||
if err := rows.Next(dest[:]); err != nil {
|
|
||||||
if err == io.EOF {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
b.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkEncodeInt64(b *testing.B) {
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
encode(¶meterStatus{}, int64(1234), oid.T_int8)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkEncodeFloat64(b *testing.B) {
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
encode(¶meterStatus{}, 3.14159, oid.T_float8)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var testByteString = []byte("abcdefghijklmnopqrstuvwxyz")
|
|
||||||
|
|
||||||
func BenchmarkEncodeByteaHex(b *testing.B) {
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
encode(¶meterStatus{serverVersion: 90000}, testByteString, oid.T_bytea)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
func BenchmarkEncodeByteaEscape(b *testing.B) {
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
encode(¶meterStatus{serverVersion: 84000}, testByteString, oid.T_bytea)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkEncodeBool(b *testing.B) {
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
encode(¶meterStatus{}, true, oid.T_bool)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var testTimestamptz = time.Date(2001, time.January, 1, 0, 0, 0, 0, time.Local)
|
|
||||||
|
|
||||||
func BenchmarkEncodeTimestamptz(b *testing.B) {
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
encode(¶meterStatus{}, testTimestamptz, oid.T_timestamptz)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var testIntBytes = []byte("1234")
|
|
||||||
|
|
||||||
func BenchmarkDecodeInt64(b *testing.B) {
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
decode(¶meterStatus{}, testIntBytes, oid.T_int8)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var testFloatBytes = []byte("3.14159")
|
|
||||||
|
|
||||||
func BenchmarkDecodeFloat64(b *testing.B) {
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
decode(¶meterStatus{}, testFloatBytes, oid.T_float8)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var testBoolBytes = []byte{'t'}
|
|
||||||
|
|
||||||
func BenchmarkDecodeBool(b *testing.B) {
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
decode(¶meterStatus{}, testBoolBytes, oid.T_bool)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestDecodeBool(t *testing.T) {
|
|
||||||
db := openTestConn(t)
|
|
||||||
rows, err := db.Query("select true")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
rows.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
var testTimestamptzBytes = []byte("2013-09-17 22:15:32.360754-07")
|
|
||||||
|
|
||||||
func BenchmarkDecodeTimestamptz(b *testing.B) {
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
decode(¶meterStatus{}, testTimestamptzBytes, oid.T_timestamptz)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkDecodeTimestamptzMultiThread(b *testing.B) {
|
|
||||||
oldProcs := runtime.GOMAXPROCS(0)
|
|
||||||
defer runtime.GOMAXPROCS(oldProcs)
|
|
||||||
runtime.GOMAXPROCS(runtime.NumCPU())
|
|
||||||
globalLocationCache = newLocationCache()
|
|
||||||
|
|
||||||
f := func(wg *sync.WaitGroup, loops int) {
|
|
||||||
defer wg.Done()
|
|
||||||
for i := 0; i < loops; i++ {
|
|
||||||
decode(¶meterStatus{}, testTimestamptzBytes, oid.T_timestamptz)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
wg := &sync.WaitGroup{}
|
|
||||||
b.ResetTimer()
|
|
||||||
for j := 0; j < 10; j++ {
|
|
||||||
wg.Add(1)
|
|
||||||
go f(wg, b.N/10)
|
|
||||||
}
|
|
||||||
wg.Wait()
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkLocationCache(b *testing.B) {
|
|
||||||
globalLocationCache = newLocationCache()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
globalLocationCache.getLocation(rand.Intn(10000))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkLocationCacheMultiThread(b *testing.B) {
|
|
||||||
oldProcs := runtime.GOMAXPROCS(0)
|
|
||||||
defer runtime.GOMAXPROCS(oldProcs)
|
|
||||||
runtime.GOMAXPROCS(runtime.NumCPU())
|
|
||||||
globalLocationCache = newLocationCache()
|
|
||||||
|
|
||||||
f := func(wg *sync.WaitGroup, loops int) {
|
|
||||||
defer wg.Done()
|
|
||||||
for i := 0; i < loops; i++ {
|
|
||||||
globalLocationCache.getLocation(rand.Intn(10000))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
wg := &sync.WaitGroup{}
|
|
||||||
b.ResetTimer()
|
|
||||||
for j := 0; j < 10; j++ {
|
|
||||||
wg.Add(1)
|
|
||||||
go f(wg, b.N/10)
|
|
||||||
}
|
|
||||||
wg.Wait()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Stress test the performance of parsing results from the wire.
|
|
||||||
func BenchmarkResultParsing(b *testing.B) {
|
|
||||||
b.StopTimer()
|
|
||||||
|
|
||||||
db := openTestConn(b)
|
|
||||||
defer db.Close()
|
|
||||||
_, err := db.Exec("BEGIN")
|
|
||||||
if err != nil {
|
|
||||||
b.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
b.StartTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
res, err := db.Query("SELECT generate_series(1, 50000)")
|
|
||||||
if err != nil {
|
|
||||||
b.Fatal(err)
|
|
||||||
}
|
|
||||||
res.Close()
|
|
||||||
}
|
|
||||||
}
|
|
1244
Godeps/_workspace/src/github.com/lib/pq/conn_test.go
generated
vendored
1244
Godeps/_workspace/src/github.com/lib/pq/conn_test.go
generated
vendored
File diff suppressed because it is too large
Load diff
61
Godeps/_workspace/src/github.com/lib/pq/conn_xact_test.go
generated
vendored
61
Godeps/_workspace/src/github.com/lib/pq/conn_xact_test.go
generated
vendored
|
@ -1,61 +0,0 @@
|
||||||
// +build go1.1
|
|
||||||
|
|
||||||
package pq
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestXactMultiStmt(t *testing.T) {
|
|
||||||
// minified test case based on bug reports from
|
|
||||||
// pico303@gmail.com and rangelspam@gmail.com
|
|
||||||
t.Skip("Skipping failing test")
|
|
||||||
db := openTestConn(t)
|
|
||||||
defer db.Close()
|
|
||||||
|
|
||||||
tx, err := db.Begin()
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
defer tx.Commit()
|
|
||||||
|
|
||||||
rows, err := tx.Query("select 1")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if rows.Next() {
|
|
||||||
var val int32
|
|
||||||
if err = rows.Scan(&val); err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
t.Fatal("Expected at least one row in first query in xact")
|
|
||||||
}
|
|
||||||
|
|
||||||
rows2, err := tx.Query("select 2")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if rows2.Next() {
|
|
||||||
var val2 int32
|
|
||||||
if err := rows2.Scan(&val2); err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
t.Fatal("Expected at least one row in second query in xact")
|
|
||||||
}
|
|
||||||
|
|
||||||
if err = rows.Err(); err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err = rows2.Err(); err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err = tx.Commit(); err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
324
Godeps/_workspace/src/github.com/lib/pq/copy_test.go
generated
vendored
324
Godeps/_workspace/src/github.com/lib/pq/copy_test.go
generated
vendored
|
@ -1,324 +0,0 @@
|
||||||
package pq
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"database/sql"
|
|
||||||
"strings"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestCopyInStmt(t *testing.T) {
|
|
||||||
var stmt string
|
|
||||||
stmt = CopyIn("table name")
|
|
||||||
if stmt != `COPY "table name" () FROM STDIN` {
|
|
||||||
t.Fatal(stmt)
|
|
||||||
}
|
|
||||||
|
|
||||||
stmt = CopyIn("table name", "column 1", "column 2")
|
|
||||||
if stmt != `COPY "table name" ("column 1", "column 2") FROM STDIN` {
|
|
||||||
t.Fatal(stmt)
|
|
||||||
}
|
|
||||||
|
|
||||||
stmt = CopyIn(`table " name """`, `co"lumn""`)
|
|
||||||
if stmt != `COPY "table "" name """"""" ("co""lumn""""") FROM STDIN` {
|
|
||||||
t.Fatal(stmt)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCopyInSchemaStmt(t *testing.T) {
|
|
||||||
var stmt string
|
|
||||||
stmt = CopyInSchema("schema name", "table name")
|
|
||||||
if stmt != `COPY "schema name"."table name" () FROM STDIN` {
|
|
||||||
t.Fatal(stmt)
|
|
||||||
}
|
|
||||||
|
|
||||||
stmt = CopyInSchema("schema name", "table name", "column 1", "column 2")
|
|
||||||
if stmt != `COPY "schema name"."table name" ("column 1", "column 2") FROM STDIN` {
|
|
||||||
t.Fatal(stmt)
|
|
||||||
}
|
|
||||||
|
|
||||||
stmt = CopyInSchema(`schema " name """`, `table " name """`, `co"lumn""`)
|
|
||||||
if stmt != `COPY "schema "" name """"""".`+
|
|
||||||
`"table "" name """"""" ("co""lumn""""") FROM STDIN` {
|
|
||||||
t.Fatal(stmt)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCopyInMultipleValues(t *testing.T) {
|
|
||||||
db := openTestConn(t)
|
|
||||||
defer db.Close()
|
|
||||||
|
|
||||||
txn, err := db.Begin()
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
defer txn.Rollback()
|
|
||||||
|
|
||||||
_, err = txn.Exec("CREATE TEMP TABLE temp (a int, b varchar)")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
stmt, err := txn.Prepare(CopyIn("temp", "a", "b"))
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
longString := strings.Repeat("#", 500)
|
|
||||||
|
|
||||||
for i := 0; i < 500; i++ {
|
|
||||||
_, err = stmt.Exec(int64(i), longString)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = stmt.Exec()
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = stmt.Close()
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
var num int
|
|
||||||
err = txn.QueryRow("SELECT COUNT(*) FROM temp").Scan(&num)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if num != 500 {
|
|
||||||
t.Fatalf("expected 500 items, not %d", num)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCopyInTypes(t *testing.T) {
|
|
||||||
db := openTestConn(t)
|
|
||||||
defer db.Close()
|
|
||||||
|
|
||||||
txn, err := db.Begin()
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
defer txn.Rollback()
|
|
||||||
|
|
||||||
_, err = txn.Exec("CREATE TEMP TABLE temp (num INTEGER, text VARCHAR, blob BYTEA, nothing VARCHAR)")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
stmt, err := txn.Prepare(CopyIn("temp", "num", "text", "blob", "nothing"))
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = stmt.Exec(int64(1234567890), "Héllö\n ☃!\r\t\\", []byte{0, 255, 9, 10, 13}, nil)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = stmt.Exec()
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = stmt.Close()
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
var num int
|
|
||||||
var text string
|
|
||||||
var blob []byte
|
|
||||||
var nothing sql.NullString
|
|
||||||
|
|
||||||
err = txn.QueryRow("SELECT * FROM temp").Scan(&num, &text, &blob, ¬hing)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if num != 1234567890 {
|
|
||||||
t.Fatal("unexpected result", num)
|
|
||||||
}
|
|
||||||
if text != "Héllö\n ☃!\r\t\\" {
|
|
||||||
t.Fatal("unexpected result", text)
|
|
||||||
}
|
|
||||||
if bytes.Compare(blob, []byte{0, 255, 9, 10, 13}) != 0 {
|
|
||||||
t.Fatal("unexpected result", blob)
|
|
||||||
}
|
|
||||||
if nothing.Valid {
|
|
||||||
t.Fatal("unexpected result", nothing.String)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCopyInWrongType(t *testing.T) {
|
|
||||||
db := openTestConn(t)
|
|
||||||
defer db.Close()
|
|
||||||
|
|
||||||
txn, err := db.Begin()
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
defer txn.Rollback()
|
|
||||||
|
|
||||||
_, err = txn.Exec("CREATE TEMP TABLE temp (num INTEGER)")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
stmt, err := txn.Prepare(CopyIn("temp", "num"))
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
defer stmt.Close()
|
|
||||||
|
|
||||||
_, err = stmt.Exec("Héllö\n ☃!\r\t\\")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = stmt.Exec()
|
|
||||||
if err == nil {
|
|
||||||
t.Fatal("expected error")
|
|
||||||
}
|
|
||||||
if pge := err.(*Error); pge.Code.Name() != "invalid_text_representation" {
|
|
||||||
t.Fatalf("expected 'invalid input syntax for integer' error, got %s (%+v)", pge.Code.Name(), pge)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCopyOutsideOfTxnError(t *testing.T) {
|
|
||||||
db := openTestConn(t)
|
|
||||||
defer db.Close()
|
|
||||||
|
|
||||||
_, err := db.Prepare(CopyIn("temp", "num"))
|
|
||||||
if err == nil {
|
|
||||||
t.Fatal("COPY outside of transaction did not return an error")
|
|
||||||
}
|
|
||||||
if err != errCopyNotSupportedOutsideTxn {
|
|
||||||
t.Fatalf("expected %s, got %s", err, err.Error())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCopyInBinaryError(t *testing.T) {
|
|
||||||
db := openTestConn(t)
|
|
||||||
defer db.Close()
|
|
||||||
|
|
||||||
txn, err := db.Begin()
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
defer txn.Rollback()
|
|
||||||
|
|
||||||
_, err = txn.Exec("CREATE TEMP TABLE temp (num INTEGER)")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
_, err = txn.Prepare("COPY temp (num) FROM STDIN WITH binary")
|
|
||||||
if err != errBinaryCopyNotSupported {
|
|
||||||
t.Fatalf("expected %s, got %+v", errBinaryCopyNotSupported, err)
|
|
||||||
}
|
|
||||||
// check that the protocol is in a valid state
|
|
||||||
err = txn.Rollback()
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCopyFromError(t *testing.T) {
|
|
||||||
db := openTestConn(t)
|
|
||||||
defer db.Close()
|
|
||||||
|
|
||||||
txn, err := db.Begin()
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
defer txn.Rollback()
|
|
||||||
|
|
||||||
_, err = txn.Exec("CREATE TEMP TABLE temp (num INTEGER)")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
_, err = txn.Prepare("COPY temp (num) TO STDOUT")
|
|
||||||
if err != errCopyToNotSupported {
|
|
||||||
t.Fatalf("expected %s, got %+v", errCopyToNotSupported, err)
|
|
||||||
}
|
|
||||||
// check that the protocol is in a valid state
|
|
||||||
err = txn.Rollback()
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCopySyntaxError(t *testing.T) {
|
|
||||||
db := openTestConn(t)
|
|
||||||
defer db.Close()
|
|
||||||
|
|
||||||
txn, err := db.Begin()
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
defer txn.Rollback()
|
|
||||||
|
|
||||||
_, err = txn.Prepare("COPY ")
|
|
||||||
if err == nil {
|
|
||||||
t.Fatal("expected error")
|
|
||||||
}
|
|
||||||
if pge := err.(*Error); pge.Code.Name() != "syntax_error" {
|
|
||||||
t.Fatalf("expected syntax error, got %s (%+v)", pge.Code.Name(), pge)
|
|
||||||
}
|
|
||||||
// check that the protocol is in a valid state
|
|
||||||
err = txn.Rollback()
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkCopyIn(b *testing.B) {
|
|
||||||
db := openTestConn(b)
|
|
||||||
defer db.Close()
|
|
||||||
|
|
||||||
txn, err := db.Begin()
|
|
||||||
if err != nil {
|
|
||||||
b.Fatal(err)
|
|
||||||
}
|
|
||||||
defer txn.Rollback()
|
|
||||||
|
|
||||||
_, err = txn.Exec("CREATE TEMP TABLE temp (a int, b varchar)")
|
|
||||||
if err != nil {
|
|
||||||
b.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
stmt, err := txn.Prepare(CopyIn("temp", "a", "b"))
|
|
||||||
if err != nil {
|
|
||||||
b.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
_, err = stmt.Exec(int64(i), "hello world!")
|
|
||||||
if err != nil {
|
|
||||||
b.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = stmt.Exec()
|
|
||||||
if err != nil {
|
|
||||||
b.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = stmt.Close()
|
|
||||||
if err != nil {
|
|
||||||
b.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
var num int
|
|
||||||
err = txn.QueryRow("SELECT COUNT(*) FROM temp").Scan(&num)
|
|
||||||
if err != nil {
|
|
||||||
b.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if num != b.N {
|
|
||||||
b.Fatalf("expected %d items, not %d", b.N, num)
|
|
||||||
}
|
|
||||||
}
|
|
427
Godeps/_workspace/src/github.com/lib/pq/encode_test.go
generated
vendored
427
Godeps/_workspace/src/github.com/lib/pq/encode_test.go
generated
vendored
|
@ -1,427 +0,0 @@
|
||||||
package pq
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/lib/pq/oid"
|
|
||||||
|
|
||||||
"bytes"
|
|
||||||
"fmt"
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestScanTimestamp(t *testing.T) {
|
|
||||||
var nt NullTime
|
|
||||||
tn := time.Now()
|
|
||||||
nt.Scan(tn)
|
|
||||||
if !nt.Valid {
|
|
||||||
t.Errorf("Expected Valid=false")
|
|
||||||
}
|
|
||||||
if nt.Time != tn {
|
|
||||||
t.Errorf("Time value mismatch")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestScanNilTimestamp(t *testing.T) {
|
|
||||||
var nt NullTime
|
|
||||||
nt.Scan(nil)
|
|
||||||
if nt.Valid {
|
|
||||||
t.Errorf("Expected Valid=false")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var timeTests = []struct {
|
|
||||||
str string
|
|
||||||
timeval time.Time
|
|
||||||
}{
|
|
||||||
{"22001-02-03", time.Date(22001, time.February, 3, 0, 0, 0, 0, time.FixedZone("", 0))},
|
|
||||||
{"2001-02-03", time.Date(2001, time.February, 3, 0, 0, 0, 0, time.FixedZone("", 0))},
|
|
||||||
{"2001-02-03 04:05:06", time.Date(2001, time.February, 3, 4, 5, 6, 0, time.FixedZone("", 0))},
|
|
||||||
{"2001-02-03 04:05:06.000001", time.Date(2001, time.February, 3, 4, 5, 6, 1000, time.FixedZone("", 0))},
|
|
||||||
{"2001-02-03 04:05:06.00001", time.Date(2001, time.February, 3, 4, 5, 6, 10000, time.FixedZone("", 0))},
|
|
||||||
{"2001-02-03 04:05:06.0001", time.Date(2001, time.February, 3, 4, 5, 6, 100000, time.FixedZone("", 0))},
|
|
||||||
{"2001-02-03 04:05:06.001", time.Date(2001, time.February, 3, 4, 5, 6, 1000000, time.FixedZone("", 0))},
|
|
||||||
{"2001-02-03 04:05:06.01", time.Date(2001, time.February, 3, 4, 5, 6, 10000000, time.FixedZone("", 0))},
|
|
||||||
{"2001-02-03 04:05:06.1", time.Date(2001, time.February, 3, 4, 5, 6, 100000000, time.FixedZone("", 0))},
|
|
||||||
{"2001-02-03 04:05:06.12", time.Date(2001, time.February, 3, 4, 5, 6, 120000000, time.FixedZone("", 0))},
|
|
||||||
{"2001-02-03 04:05:06.123", time.Date(2001, time.February, 3, 4, 5, 6, 123000000, time.FixedZone("", 0))},
|
|
||||||
{"2001-02-03 04:05:06.1234", time.Date(2001, time.February, 3, 4, 5, 6, 123400000, time.FixedZone("", 0))},
|
|
||||||
{"2001-02-03 04:05:06.12345", time.Date(2001, time.February, 3, 4, 5, 6, 123450000, time.FixedZone("", 0))},
|
|
||||||
{"2001-02-03 04:05:06.123456", time.Date(2001, time.February, 3, 4, 5, 6, 123456000, time.FixedZone("", 0))},
|
|
||||||
{"2001-02-03 04:05:06.123-07", time.Date(2001, time.February, 3, 4, 5, 6, 123000000,
|
|
||||||
time.FixedZone("", -7*60*60))},
|
|
||||||
{"2001-02-03 04:05:06-07", time.Date(2001, time.February, 3, 4, 5, 6, 0,
|
|
||||||
time.FixedZone("", -7*60*60))},
|
|
||||||
{"2001-02-03 04:05:06-07:42", time.Date(2001, time.February, 3, 4, 5, 6, 0,
|
|
||||||
time.FixedZone("", -(7*60*60+42*60)))},
|
|
||||||
{"2001-02-03 04:05:06-07:30:09", time.Date(2001, time.February, 3, 4, 5, 6, 0,
|
|
||||||
time.FixedZone("", -(7*60*60+30*60+9)))},
|
|
||||||
{"2001-02-03 04:05:06+07", time.Date(2001, time.February, 3, 4, 5, 6, 0,
|
|
||||||
time.FixedZone("", 7*60*60))},
|
|
||||||
//{"10000-02-03 04:05:06 BC", time.Date(-10000, time.February, 3, 4, 5, 6, 0, time.FixedZone("", 0))},
|
|
||||||
{"0010-02-03 04:05:06 BC", time.Date(-10, time.February, 3, 4, 5, 6, 0, time.FixedZone("", 0))},
|
|
||||||
{"0010-02-03 04:05:06.123 BC", time.Date(-10, time.February, 3, 4, 5, 6, 123000000, time.FixedZone("", 0))},
|
|
||||||
{"0010-02-03 04:05:06.123-07 BC", time.Date(-10, time.February, 3, 4, 5, 6, 123000000,
|
|
||||||
time.FixedZone("", -7*60*60))},
|
|
||||||
}
|
|
||||||
|
|
||||||
// Helper function for the two tests below
|
|
||||||
func tryParse(str string) (t time.Time, err error) {
|
|
||||||
defer func() {
|
|
||||||
if p := recover(); p != nil {
|
|
||||||
err = fmt.Errorf("%v", p)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
t = parseTs(nil, str)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test that parsing the string results in the expected value.
|
|
||||||
func TestParseTs(t *testing.T) {
|
|
||||||
for i, tt := range timeTests {
|
|
||||||
val, err := tryParse(tt.str)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("%d: got error: %v", i, err)
|
|
||||||
} else if val.String() != tt.timeval.String() {
|
|
||||||
t.Errorf("%d: expected to parse %q into %q; got %q",
|
|
||||||
i, tt.str, tt.timeval, val)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now test that sending the value into the database and parsing it back
|
|
||||||
// returns the same time.Time value.
|
|
||||||
func TestEncodeAndParseTs(t *testing.T) {
|
|
||||||
db, err := openTestConnConninfo("timezone='Etc/UTC'")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
defer db.Close()
|
|
||||||
|
|
||||||
for i, tt := range timeTests {
|
|
||||||
var dbstr string
|
|
||||||
err = db.QueryRow("SELECT ($1::timestamptz)::text", tt.timeval).Scan(&dbstr)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("%d: could not send value %q to the database: %s", i, tt.timeval, err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
val, err := tryParse(dbstr)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("%d: could not parse value %q: %s", i, dbstr, err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
val = val.In(tt.timeval.Location())
|
|
||||||
if val.String() != tt.timeval.String() {
|
|
||||||
t.Errorf("%d: expected to parse %q into %q; got %q", i, dbstr, tt.timeval, val)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var formatTimeTests = []struct {
|
|
||||||
time time.Time
|
|
||||||
expected string
|
|
||||||
}{
|
|
||||||
{time.Time{}, "0001-01-01T00:00:00Z"},
|
|
||||||
{time.Date(2001, time.February, 3, 4, 5, 6, 123456789, time.FixedZone("", 0)), "2001-02-03T04:05:06.123456789Z"},
|
|
||||||
{time.Date(2001, time.February, 3, 4, 5, 6, 123456789, time.FixedZone("", 2*60*60)), "2001-02-03T04:05:06.123456789+02:00"},
|
|
||||||
{time.Date(2001, time.February, 3, 4, 5, 6, 123456789, time.FixedZone("", -6*60*60)), "2001-02-03T04:05:06.123456789-06:00"},
|
|
||||||
{time.Date(1, time.January, 1, 0, 0, 0, 0, time.FixedZone("", 19*60+32)), "0001-01-01T00:00:00+00:19:32"},
|
|
||||||
{time.Date(2001, time.February, 3, 4, 5, 6, 0, time.FixedZone("", -(7*60*60+30*60+9))), "2001-02-03T04:05:06-07:30:09"},
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFormatTs(t *testing.T) {
|
|
||||||
for i, tt := range formatTimeTests {
|
|
||||||
val := string(formatTs(tt.time))
|
|
||||||
if val != tt.expected {
|
|
||||||
t.Errorf("%d: incorrect time format %q, want %q", i, val, tt.expected)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTimestampWithTimeZone(t *testing.T) {
|
|
||||||
db := openTestConn(t)
|
|
||||||
defer db.Close()
|
|
||||||
|
|
||||||
tx, err := db.Begin()
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
defer tx.Rollback()
|
|
||||||
|
|
||||||
// try several different locations, all included in Go's zoneinfo.zip
|
|
||||||
for _, locName := range []string{
|
|
||||||
"UTC",
|
|
||||||
"America/Chicago",
|
|
||||||
"America/New_York",
|
|
||||||
"Australia/Darwin",
|
|
||||||
"Australia/Perth",
|
|
||||||
} {
|
|
||||||
loc, err := time.LoadLocation(locName)
|
|
||||||
if err != nil {
|
|
||||||
t.Logf("Could not load time zone %s - skipping", locName)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// Postgres timestamps have a resolution of 1 microsecond, so don't
|
|
||||||
// use the full range of the Nanosecond argument
|
|
||||||
refTime := time.Date(2012, 11, 6, 10, 23, 42, 123456000, loc)
|
|
||||||
|
|
||||||
for _, pgTimeZone := range []string{"US/Eastern", "Australia/Darwin"} {
|
|
||||||
// Switch Postgres's timezone to test different output timestamp formats
|
|
||||||
_, err = tx.Exec(fmt.Sprintf("set time zone '%s'", pgTimeZone))
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
var gotTime time.Time
|
|
||||||
row := tx.QueryRow("select $1::timestamp with time zone", refTime)
|
|
||||||
err = row.Scan(&gotTime)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !refTime.Equal(gotTime) {
|
|
||||||
t.Errorf("timestamps not equal: %s != %s", refTime, gotTime)
|
|
||||||
}
|
|
||||||
|
|
||||||
// check that the time zone is set correctly based on TimeZone
|
|
||||||
pgLoc, err := time.LoadLocation(pgTimeZone)
|
|
||||||
if err != nil {
|
|
||||||
t.Logf("Could not load time zone %s - skipping", pgLoc)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
translated := refTime.In(pgLoc)
|
|
||||||
if translated.String() != gotTime.String() {
|
|
||||||
t.Errorf("timestamps not equal: %s != %s", translated, gotTime)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTimestampWithOutTimezone(t *testing.T) {
|
|
||||||
db := openTestConn(t)
|
|
||||||
defer db.Close()
|
|
||||||
|
|
||||||
test := func(ts, pgts string) {
|
|
||||||
r, err := db.Query("SELECT $1::timestamp", pgts)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Could not run query: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
n := r.Next()
|
|
||||||
|
|
||||||
if n != true {
|
|
||||||
t.Fatal("Expected at least one row")
|
|
||||||
}
|
|
||||||
|
|
||||||
var result time.Time
|
|
||||||
err = r.Scan(&result)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Did not expect error scanning row: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
expected, err := time.Parse(time.RFC3339, ts)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Could not parse test time literal: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !result.Equal(expected) {
|
|
||||||
t.Fatalf("Expected time to match %v: got mismatch %v",
|
|
||||||
expected, result)
|
|
||||||
}
|
|
||||||
|
|
||||||
n = r.Next()
|
|
||||||
if n != false {
|
|
||||||
t.Fatal("Expected only one row")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
test("2000-01-01T00:00:00Z", "2000-01-01T00:00:00")
|
|
||||||
|
|
||||||
// Test higher precision time
|
|
||||||
test("2013-01-04T20:14:58.80033Z", "2013-01-04 20:14:58.80033")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestStringWithNul(t *testing.T) {
|
|
||||||
db := openTestConn(t)
|
|
||||||
defer db.Close()
|
|
||||||
|
|
||||||
hello0world := string("hello\x00world")
|
|
||||||
_, err := db.Query("SELECT $1::text", &hello0world)
|
|
||||||
if err == nil {
|
|
||||||
t.Fatal("Postgres accepts a string with nul in it; " +
|
|
||||||
"injection attacks may be plausible")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestByteaToText(t *testing.T) {
|
|
||||||
db := openTestConn(t)
|
|
||||||
defer db.Close()
|
|
||||||
|
|
||||||
b := []byte("hello world")
|
|
||||||
row := db.QueryRow("SELECT $1::text", b)
|
|
||||||
|
|
||||||
var result []byte
|
|
||||||
err := row.Scan(&result)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if string(result) != string(b) {
|
|
||||||
t.Fatalf("expected %v but got %v", b, result)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTextToBytea(t *testing.T) {
|
|
||||||
db := openTestConn(t)
|
|
||||||
defer db.Close()
|
|
||||||
|
|
||||||
b := "hello world"
|
|
||||||
row := db.QueryRow("SELECT $1::bytea", b)
|
|
||||||
|
|
||||||
var result []byte
|
|
||||||
err := row.Scan(&result)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !bytes.Equal(result, []byte(b)) {
|
|
||||||
t.Fatalf("expected %v but got %v", b, result)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestByteaOutputFormatEncoding(t *testing.T) {
|
|
||||||
input := []byte("\\x\x00\x01\x02\xFF\xFEabcdefg0123")
|
|
||||||
want := []byte("\\x5c78000102fffe6162636465666730313233")
|
|
||||||
got := encode(¶meterStatus{serverVersion: 90000}, input, oid.T_bytea)
|
|
||||||
if !bytes.Equal(want, got) {
|
|
||||||
t.Errorf("invalid hex bytea output, got %v but expected %v", got, want)
|
|
||||||
}
|
|
||||||
|
|
||||||
want = []byte("\\\\x\\000\\001\\002\\377\\376abcdefg0123")
|
|
||||||
got = encode(¶meterStatus{serverVersion: 84000}, input, oid.T_bytea)
|
|
||||||
if !bytes.Equal(want, got) {
|
|
||||||
t.Errorf("invalid escape bytea output, got %v but expected %v", got, want)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestByteaOutputFormats(t *testing.T) {
|
|
||||||
db := openTestConn(t)
|
|
||||||
defer db.Close()
|
|
||||||
|
|
||||||
if getServerVersion(t, db) < 90000 {
|
|
||||||
// skip
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
testByteaOutputFormat := func(f string) {
|
|
||||||
expectedData := []byte("\x5c\x78\x00\xff\x61\x62\x63\x01\x08")
|
|
||||||
sqlQuery := "SELECT decode('5c7800ff6162630108', 'hex')"
|
|
||||||
|
|
||||||
var data []byte
|
|
||||||
|
|
||||||
// use a txn to avoid relying on getting the same connection
|
|
||||||
txn, err := db.Begin()
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
defer txn.Rollback()
|
|
||||||
|
|
||||||
_, err = txn.Exec("SET LOCAL bytea_output TO " + f)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
// use Query; QueryRow would hide the actual error
|
|
||||||
rows, err := txn.Query(sqlQuery)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
if !rows.Next() {
|
|
||||||
if rows.Err() != nil {
|
|
||||||
t.Fatal(rows.Err())
|
|
||||||
}
|
|
||||||
t.Fatal("shouldn't happen")
|
|
||||||
}
|
|
||||||
err = rows.Scan(&data)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
err = rows.Close()
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
if !bytes.Equal(data, expectedData) {
|
|
||||||
t.Errorf("unexpected bytea value %v for format %s; expected %v", data, f, expectedData)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
testByteaOutputFormat("hex")
|
|
||||||
testByteaOutputFormat("escape")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestAppendEncodedText(t *testing.T) {
|
|
||||||
var buf []byte
|
|
||||||
|
|
||||||
buf = appendEncodedText(¶meterStatus{serverVersion: 90000}, buf, int64(10))
|
|
||||||
buf = append(buf, '\t')
|
|
||||||
buf = appendEncodedText(¶meterStatus{serverVersion: 90000}, buf, float32(42.0000000001))
|
|
||||||
buf = append(buf, '\t')
|
|
||||||
buf = appendEncodedText(¶meterStatus{serverVersion: 90000}, buf, 42.0000000001)
|
|
||||||
buf = append(buf, '\t')
|
|
||||||
buf = appendEncodedText(¶meterStatus{serverVersion: 90000}, buf, "hello\tworld")
|
|
||||||
buf = append(buf, '\t')
|
|
||||||
buf = appendEncodedText(¶meterStatus{serverVersion: 90000}, buf, []byte{0, 128, 255})
|
|
||||||
|
|
||||||
if string(buf) != "10\t42\t42.0000000001\thello\\tworld\t\\\\x0080ff" {
|
|
||||||
t.Fatal(string(buf))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestAppendEscapedText(t *testing.T) {
|
|
||||||
if esc := appendEscapedText(nil, "hallo\tescape"); string(esc) != "hallo\\tescape" {
|
|
||||||
t.Fatal(string(esc))
|
|
||||||
}
|
|
||||||
if esc := appendEscapedText(nil, "hallo\\tescape\n"); string(esc) != "hallo\\\\tescape\\n" {
|
|
||||||
t.Fatal(string(esc))
|
|
||||||
}
|
|
||||||
if esc := appendEscapedText(nil, "\n\r\t\f"); string(esc) != "\\n\\r\\t\f" {
|
|
||||||
t.Fatal(string(esc))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestAppendEscapedTextExistingBuffer(t *testing.T) {
|
|
||||||
var buf []byte
|
|
||||||
buf = []byte("123\t")
|
|
||||||
if esc := appendEscapedText(buf, "hallo\tescape"); string(esc) != "123\thallo\\tescape" {
|
|
||||||
t.Fatal(string(esc))
|
|
||||||
}
|
|
||||||
buf = []byte("123\t")
|
|
||||||
if esc := appendEscapedText(buf, "hallo\\tescape\n"); string(esc) != "123\thallo\\\\tescape\\n" {
|
|
||||||
t.Fatal(string(esc))
|
|
||||||
}
|
|
||||||
buf = []byte("123\t")
|
|
||||||
if esc := appendEscapedText(buf, "\n\r\t\f"); string(esc) != "123\t\\n\\r\\t\f" {
|
|
||||||
t.Fatal(string(esc))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkAppendEscapedText(b *testing.B) {
|
|
||||||
longString := ""
|
|
||||||
for i := 0; i < 100; i++ {
|
|
||||||
longString += "123456789\n"
|
|
||||||
}
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
appendEscapedText(nil, longString)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkAppendEscapedTextNoEscape(b *testing.B) {
|
|
||||||
longString := ""
|
|
||||||
for i := 0; i < 100; i++ {
|
|
||||||
longString += "1234567890"
|
|
||||||
}
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
appendEscapedText(nil, longString)
|
|
||||||
}
|
|
||||||
}
|
|
148
Godeps/_workspace/src/github.com/lib/pq/hstore/hstore_test.go
generated
vendored
148
Godeps/_workspace/src/github.com/lib/pq/hstore/hstore_test.go
generated
vendored
|
@ -1,148 +0,0 @@
|
||||||
package hstore
|
|
||||||
|
|
||||||
import (
|
|
||||||
"database/sql"
|
|
||||||
_ "github.com/lib/pq"
|
|
||||||
"os"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Fatalistic interface {
|
|
||||||
Fatal(args ...interface{})
|
|
||||||
}
|
|
||||||
|
|
||||||
func openTestConn(t Fatalistic) *sql.DB {
|
|
||||||
datname := os.Getenv("PGDATABASE")
|
|
||||||
sslmode := os.Getenv("PGSSLMODE")
|
|
||||||
|
|
||||||
if datname == "" {
|
|
||||||
os.Setenv("PGDATABASE", "pqgotest")
|
|
||||||
}
|
|
||||||
|
|
||||||
if sslmode == "" {
|
|
||||||
os.Setenv("PGSSLMODE", "disable")
|
|
||||||
}
|
|
||||||
|
|
||||||
conn, err := sql.Open("postgres", "")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return conn
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestHstore(t *testing.T) {
|
|
||||||
db := openTestConn(t)
|
|
||||||
defer db.Close()
|
|
||||||
|
|
||||||
// quitely create hstore if it doesn't exist
|
|
||||||
_, err := db.Exec("CREATE EXTENSION IF NOT EXISTS hstore")
|
|
||||||
if err != nil {
|
|
||||||
t.Log("Skipping hstore tests - hstore extension create failed. " + err.Error())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
hs := Hstore{}
|
|
||||||
|
|
||||||
// test for null-valued hstores
|
|
||||||
err = db.QueryRow("SELECT NULL::hstore").Scan(&hs)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
if hs.Map != nil {
|
|
||||||
t.Fatalf("expected null map")
|
|
||||||
}
|
|
||||||
|
|
||||||
err = db.QueryRow("SELECT $1::hstore", hs).Scan(&hs)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("re-query null map failed: %s", err.Error())
|
|
||||||
}
|
|
||||||
if hs.Map != nil {
|
|
||||||
t.Fatalf("expected null map")
|
|
||||||
}
|
|
||||||
|
|
||||||
// test for empty hstores
|
|
||||||
err = db.QueryRow("SELECT ''::hstore").Scan(&hs)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
if hs.Map == nil {
|
|
||||||
t.Fatalf("expected empty map, got null map")
|
|
||||||
}
|
|
||||||
if len(hs.Map) != 0 {
|
|
||||||
t.Fatalf("expected empty map, got len(map)=%d", len(hs.Map))
|
|
||||||
}
|
|
||||||
|
|
||||||
err = db.QueryRow("SELECT $1::hstore", hs).Scan(&hs)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("re-query empty map failed: %s", err.Error())
|
|
||||||
}
|
|
||||||
if hs.Map == nil {
|
|
||||||
t.Fatalf("expected empty map, got null map")
|
|
||||||
}
|
|
||||||
if len(hs.Map) != 0 {
|
|
||||||
t.Fatalf("expected empty map, got len(map)=%d", len(hs.Map))
|
|
||||||
}
|
|
||||||
|
|
||||||
// a few example maps to test out
|
|
||||||
hsOnePair := Hstore{
|
|
||||||
Map: map[string]sql.NullString{
|
|
||||||
"key1": {"value1", true},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
hsThreePairs := Hstore{
|
|
||||||
Map: map[string]sql.NullString{
|
|
||||||
"key1": {"value1", true},
|
|
||||||
"key2": {"value2", true},
|
|
||||||
"key3": {"value3", true},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
hsSmorgasbord := Hstore{
|
|
||||||
Map: map[string]sql.NullString{
|
|
||||||
"nullstring": {"NULL", true},
|
|
||||||
"actuallynull": {"", false},
|
|
||||||
"NULL": {"NULL string key", true},
|
|
||||||
"withbracket": {"value>42", true},
|
|
||||||
"withequal": {"value=42", true},
|
|
||||||
`"withquotes1"`: {`this "should" be fine`, true},
|
|
||||||
`"withquotes"2"`: {`this "should\" also be fine`, true},
|
|
||||||
"embedded1": {"value1=>x1", true},
|
|
||||||
"embedded2": {`"value2"=>x2`, true},
|
|
||||||
"withnewlines": {"\n\nvalue\t=>2", true},
|
|
||||||
"<<all sorts of crazy>>": {`this, "should,\" also, => be fine`, true},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
// test encoding in query params, then decoding during Scan
|
|
||||||
testBidirectional := func(h Hstore) {
|
|
||||||
err = db.QueryRow("SELECT $1::hstore", h).Scan(&hs)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("re-query %d-pair map failed: %s", len(h.Map), err.Error())
|
|
||||||
}
|
|
||||||
if hs.Map == nil {
|
|
||||||
t.Fatalf("expected %d-pair map, got null map", len(h.Map))
|
|
||||||
}
|
|
||||||
if len(hs.Map) != len(h.Map) {
|
|
||||||
t.Fatalf("expected %d-pair map, got len(map)=%d", len(h.Map), len(hs.Map))
|
|
||||||
}
|
|
||||||
|
|
||||||
for key, val := range hs.Map {
|
|
||||||
otherval, found := h.Map[key]
|
|
||||||
if !found {
|
|
||||||
t.Fatalf(" key '%v' not found in %d-pair map", key, len(h.Map))
|
|
||||||
}
|
|
||||||
if otherval.Valid != val.Valid {
|
|
||||||
t.Fatalf(" value %v <> %v in %d-pair map", otherval, val, len(h.Map))
|
|
||||||
}
|
|
||||||
if otherval.String != val.String {
|
|
||||||
t.Fatalf(" value '%v' <> '%v' in %d-pair map", otherval.String, val.String, len(h.Map))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
testBidirectional(hsOnePair)
|
|
||||||
testBidirectional(hsThreePairs)
|
|
||||||
testBidirectional(hsSmorgasbord)
|
|
||||||
}
|
|
507
Godeps/_workspace/src/github.com/lib/pq/notify_test.go
generated
vendored
507
Godeps/_workspace/src/github.com/lib/pq/notify_test.go
generated
vendored
|
@ -1,507 +0,0 @@
|
||||||
package pq
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"os"
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
var errNilNotification = errors.New("nil notification")
|
|
||||||
|
|
||||||
func expectNotification(t *testing.T, ch <-chan *Notification, relname string, extra string) error {
|
|
||||||
select {
|
|
||||||
case n := <-ch:
|
|
||||||
if n == nil {
|
|
||||||
return errNilNotification
|
|
||||||
}
|
|
||||||
if n.Channel != relname || n.Extra != extra {
|
|
||||||
return fmt.Errorf("unexpected notification %v", n)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
case <-time.After(1500 * time.Millisecond):
|
|
||||||
return fmt.Errorf("timeout")
|
|
||||||
}
|
|
||||||
panic("not reached")
|
|
||||||
}
|
|
||||||
|
|
||||||
func expectNoNotification(t *testing.T, ch <-chan *Notification) error {
|
|
||||||
select {
|
|
||||||
case n := <-ch:
|
|
||||||
return fmt.Errorf("unexpected notification %v", n)
|
|
||||||
case <-time.After(100 * time.Millisecond):
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
panic("not reached")
|
|
||||||
}
|
|
||||||
|
|
||||||
func expectEvent(t *testing.T, eventch <-chan ListenerEventType, et ListenerEventType) error {
|
|
||||||
select {
|
|
||||||
case e := <-eventch:
|
|
||||||
if e != et {
|
|
||||||
return fmt.Errorf("unexpected event %v", e)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
case <-time.After(1500 * time.Millisecond):
|
|
||||||
return fmt.Errorf("timeout")
|
|
||||||
}
|
|
||||||
panic("not reached")
|
|
||||||
}
|
|
||||||
|
|
||||||
func expectNoEvent(t *testing.T, eventch <-chan ListenerEventType) error {
|
|
||||||
select {
|
|
||||||
case e := <-eventch:
|
|
||||||
return fmt.Errorf("unexpected event %v", e)
|
|
||||||
case <-time.After(100 * time.Millisecond):
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
panic("not reached")
|
|
||||||
}
|
|
||||||
|
|
||||||
func newTestListenerConn(t *testing.T) (*ListenerConn, <-chan *Notification) {
|
|
||||||
datname := os.Getenv("PGDATABASE")
|
|
||||||
sslmode := os.Getenv("PGSSLMODE")
|
|
||||||
|
|
||||||
if datname == "" {
|
|
||||||
os.Setenv("PGDATABASE", "pqgotest")
|
|
||||||
}
|
|
||||||
|
|
||||||
if sslmode == "" {
|
|
||||||
os.Setenv("PGSSLMODE", "disable")
|
|
||||||
}
|
|
||||||
|
|
||||||
notificationChan := make(chan *Notification)
|
|
||||||
l, err := NewListenerConn("", notificationChan)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return l, notificationChan
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestNewListenerConn(t *testing.T) {
|
|
||||||
l, _ := newTestListenerConn(t)
|
|
||||||
|
|
||||||
defer l.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestConnListen(t *testing.T) {
|
|
||||||
l, channel := newTestListenerConn(t)
|
|
||||||
|
|
||||||
defer l.Close()
|
|
||||||
|
|
||||||
db := openTestConn(t)
|
|
||||||
defer db.Close()
|
|
||||||
|
|
||||||
ok, err := l.Listen("notify_test")
|
|
||||||
if !ok || err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = db.Exec("NOTIFY notify_test")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = expectNotification(t, channel, "notify_test", "")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestConnUnlisten(t *testing.T) {
|
|
||||||
l, channel := newTestListenerConn(t)
|
|
||||||
|
|
||||||
defer l.Close()
|
|
||||||
|
|
||||||
db := openTestConn(t)
|
|
||||||
defer db.Close()
|
|
||||||
|
|
||||||
ok, err := l.Listen("notify_test")
|
|
||||||
if !ok || err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = db.Exec("NOTIFY notify_test")
|
|
||||||
|
|
||||||
err = expectNotification(t, channel, "notify_test", "")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
ok, err = l.Unlisten("notify_test")
|
|
||||||
if !ok || err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = db.Exec("NOTIFY notify_test")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = expectNoNotification(t, channel)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestConnUnlistenAll(t *testing.T) {
|
|
||||||
l, channel := newTestListenerConn(t)
|
|
||||||
|
|
||||||
defer l.Close()
|
|
||||||
|
|
||||||
db := openTestConn(t)
|
|
||||||
defer db.Close()
|
|
||||||
|
|
||||||
ok, err := l.Listen("notify_test")
|
|
||||||
if !ok || err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = db.Exec("NOTIFY notify_test")
|
|
||||||
|
|
||||||
err = expectNotification(t, channel, "notify_test", "")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
ok, err = l.UnlistenAll()
|
|
||||||
if !ok || err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = db.Exec("NOTIFY notify_test")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = expectNoNotification(t, channel)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestConnClose(t *testing.T) {
|
|
||||||
l, _ := newTestListenerConn(t)
|
|
||||||
defer l.Close()
|
|
||||||
|
|
||||||
err := l.Close()
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
err = l.Close()
|
|
||||||
if err != errListenerConnClosed {
|
|
||||||
t.Fatalf("expected errListenerConnClosed; got %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestConnPing(t *testing.T) {
|
|
||||||
l, _ := newTestListenerConn(t)
|
|
||||||
defer l.Close()
|
|
||||||
err := l.Ping()
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
err = l.Close()
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
err = l.Ping()
|
|
||||||
if err != errListenerConnClosed {
|
|
||||||
t.Fatalf("expected errListenerConnClosed; got %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestNotifyExtra(t *testing.T) {
|
|
||||||
db := openTestConn(t)
|
|
||||||
defer db.Close()
|
|
||||||
|
|
||||||
if getServerVersion(t, db) < 90000 {
|
|
||||||
t.Log("skipping test due to old PG version")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
l, channel := newTestListenerConn(t)
|
|
||||||
defer l.Close()
|
|
||||||
|
|
||||||
ok, err := l.Listen("notify_test")
|
|
||||||
if !ok || err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = db.Exec("NOTIFY notify_test, 'something'")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = expectNotification(t, channel, "notify_test", "something")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// create a new test listener and also set the timeouts
|
|
||||||
func newTestListenerTimeout(t *testing.T, min time.Duration, max time.Duration) (*Listener, <-chan ListenerEventType) {
|
|
||||||
datname := os.Getenv("PGDATABASE")
|
|
||||||
sslmode := os.Getenv("PGSSLMODE")
|
|
||||||
|
|
||||||
if datname == "" {
|
|
||||||
os.Setenv("PGDATABASE", "pqgotest")
|
|
||||||
}
|
|
||||||
|
|
||||||
if sslmode == "" {
|
|
||||||
os.Setenv("PGSSLMODE", "disable")
|
|
||||||
}
|
|
||||||
|
|
||||||
eventch := make(chan ListenerEventType, 16)
|
|
||||||
l := NewListener("", min, max, func(t ListenerEventType, err error) { eventch <- t })
|
|
||||||
err := expectEvent(t, eventch, ListenerEventConnected)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
return l, eventch
|
|
||||||
}
|
|
||||||
|
|
||||||
func newTestListener(t *testing.T) (*Listener, <-chan ListenerEventType) {
|
|
||||||
return newTestListenerTimeout(t, time.Hour, time.Hour)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestListenerListen(t *testing.T) {
|
|
||||||
l, _ := newTestListener(t)
|
|
||||||
defer l.Close()
|
|
||||||
|
|
||||||
db := openTestConn(t)
|
|
||||||
defer db.Close()
|
|
||||||
|
|
||||||
err := l.Listen("notify_listen_test")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = db.Exec("NOTIFY notify_listen_test")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = expectNotification(t, l.Notify, "notify_listen_test", "")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestListenerUnlisten(t *testing.T) {
|
|
||||||
l, _ := newTestListener(t)
|
|
||||||
defer l.Close()
|
|
||||||
|
|
||||||
db := openTestConn(t)
|
|
||||||
defer db.Close()
|
|
||||||
|
|
||||||
err := l.Listen("notify_listen_test")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = db.Exec("NOTIFY notify_listen_test")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = l.Unlisten("notify_listen_test")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = expectNotification(t, l.Notify, "notify_listen_test", "")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = db.Exec("NOTIFY notify_listen_test")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = expectNoNotification(t, l.Notify)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestListenerUnlistenAll(t *testing.T) {
|
|
||||||
l, _ := newTestListener(t)
|
|
||||||
defer l.Close()
|
|
||||||
|
|
||||||
db := openTestConn(t)
|
|
||||||
defer db.Close()
|
|
||||||
|
|
||||||
err := l.Listen("notify_listen_test")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = db.Exec("NOTIFY notify_listen_test")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = l.UnlistenAll()
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = expectNotification(t, l.Notify, "notify_listen_test", "")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = db.Exec("NOTIFY notify_listen_test")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = expectNoNotification(t, l.Notify)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestListenerFailedQuery(t *testing.T) {
|
|
||||||
l, eventch := newTestListener(t)
|
|
||||||
defer l.Close()
|
|
||||||
|
|
||||||
db := openTestConn(t)
|
|
||||||
defer db.Close()
|
|
||||||
|
|
||||||
err := l.Listen("notify_listen_test")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = db.Exec("NOTIFY notify_listen_test")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = expectNotification(t, l.Notify, "notify_listen_test", "")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// shouldn't cause a disconnect
|
|
||||||
ok, err := l.cn.ExecSimpleQuery("SELECT error")
|
|
||||||
if !ok {
|
|
||||||
t.Fatalf("could not send query to server: %v", err)
|
|
||||||
}
|
|
||||||
_, ok = err.(PGError)
|
|
||||||
if !ok {
|
|
||||||
t.Fatalf("unexpected error %v", err)
|
|
||||||
}
|
|
||||||
err = expectNoEvent(t, eventch)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// should still work
|
|
||||||
_, err = db.Exec("NOTIFY notify_listen_test")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = expectNotification(t, l.Notify, "notify_listen_test", "")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestListenerReconnect(t *testing.T) {
|
|
||||||
l, eventch := newTestListenerTimeout(t, 20*time.Millisecond, time.Hour)
|
|
||||||
defer l.Close()
|
|
||||||
|
|
||||||
db := openTestConn(t)
|
|
||||||
defer db.Close()
|
|
||||||
|
|
||||||
err := l.Listen("notify_listen_test")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = db.Exec("NOTIFY notify_listen_test")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = expectNotification(t, l.Notify, "notify_listen_test", "")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// kill the connection and make sure it comes back up
|
|
||||||
ok, err := l.cn.ExecSimpleQuery("SELECT pg_terminate_backend(pg_backend_pid())")
|
|
||||||
if ok {
|
|
||||||
t.Fatalf("could not kill the connection: %v", err)
|
|
||||||
}
|
|
||||||
if err != io.EOF {
|
|
||||||
t.Fatalf("unexpected error %v", err)
|
|
||||||
}
|
|
||||||
err = expectEvent(t, eventch, ListenerEventDisconnected)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
err = expectEvent(t, eventch, ListenerEventReconnected)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// should still work
|
|
||||||
_, err = db.Exec("NOTIFY notify_listen_test")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// should get nil after Reconnected
|
|
||||||
err = expectNotification(t, l.Notify, "", "")
|
|
||||||
if err != errNilNotification {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = expectNotification(t, l.Notify, "notify_listen_test", "")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestListenerClose(t *testing.T) {
|
|
||||||
l, _ := newTestListenerTimeout(t, 20*time.Millisecond, time.Hour)
|
|
||||||
defer l.Close()
|
|
||||||
|
|
||||||
err := l.Close()
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
err = l.Close()
|
|
||||||
if err != errListenerClosed {
|
|
||||||
t.Fatalf("expected errListenerClosed; got %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestListenerPing(t *testing.T) {
|
|
||||||
l, _ := newTestListenerTimeout(t, 20*time.Millisecond, time.Hour)
|
|
||||||
defer l.Close()
|
|
||||||
|
|
||||||
err := l.Ping()
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = l.Close()
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = l.Ping()
|
|
||||||
if err != errListenerClosed {
|
|
||||||
t.Fatalf("expected errListenerClosed; got %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
244
Godeps/_workspace/src/github.com/lib/pq/ssl_test.go
generated
vendored
244
Godeps/_workspace/src/github.com/lib/pq/ssl_test.go
generated
vendored
|
@ -1,244 +0,0 @@
|
||||||
package pq
|
|
||||||
|
|
||||||
// This file contains SSL tests
|
|
||||||
|
|
||||||
import (
|
|
||||||
_ "crypto/sha256"
|
|
||||||
"crypto/x509"
|
|
||||||
"database/sql"
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func shouldSkipSSLTests(t *testing.T) bool {
|
|
||||||
// Require some special variables for testing certificates
|
|
||||||
if os.Getenv("PQSSLCERTTEST_PATH") == "" {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
value := os.Getenv("PQGOSSLTESTS")
|
|
||||||
if value == "" || value == "0" {
|
|
||||||
return true
|
|
||||||
} else if value == "1" {
|
|
||||||
return false
|
|
||||||
} else {
|
|
||||||
t.Fatalf("unexpected value %q for PQGOSSLTESTS", value)
|
|
||||||
}
|
|
||||||
panic("not reached")
|
|
||||||
}
|
|
||||||
|
|
||||||
func openSSLConn(t *testing.T, conninfo string) (*sql.DB, error) {
|
|
||||||
db, err := openTestConnConninfo(conninfo)
|
|
||||||
if err != nil {
|
|
||||||
// should never fail
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
// Do something with the connection to see whether it's working or not.
|
|
||||||
tx, err := db.Begin()
|
|
||||||
if err == nil {
|
|
||||||
return db, tx.Rollback()
|
|
||||||
}
|
|
||||||
_ = db.Close()
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func checkSSLSetup(t *testing.T, conninfo string) {
|
|
||||||
db, err := openSSLConn(t, conninfo)
|
|
||||||
if err == nil {
|
|
||||||
db.Close()
|
|
||||||
t.Fatal("expected error with conninfo=%q", conninfo)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Connect over SSL and run a simple query to test the basics
|
|
||||||
func TestSSLConnection(t *testing.T) {
|
|
||||||
if shouldSkipSSLTests(t) {
|
|
||||||
t.Log("skipping SSL test")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// Environment sanity check: should fail without SSL
|
|
||||||
checkSSLSetup(t, "sslmode=disable user=pqgossltest")
|
|
||||||
|
|
||||||
db, err := openSSLConn(t, "sslmode=require user=pqgossltest")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
rows, err := db.Query("SELECT 1")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
rows.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test sslmode=verify-full
|
|
||||||
func TestSSLVerifyFull(t *testing.T) {
|
|
||||||
if shouldSkipSSLTests(t) {
|
|
||||||
t.Log("skipping SSL test")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// Environment sanity check: should fail without SSL
|
|
||||||
checkSSLSetup(t, "sslmode=disable user=pqgossltest")
|
|
||||||
|
|
||||||
// Not OK according to the system CA
|
|
||||||
_, err := openSSLConn(t, "host=postgres sslmode=verify-full user=pqgossltest")
|
|
||||||
if err == nil {
|
|
||||||
t.Fatal("expected error")
|
|
||||||
}
|
|
||||||
_, ok := err.(x509.UnknownAuthorityError)
|
|
||||||
if !ok {
|
|
||||||
t.Fatalf("expected x509.UnknownAuthorityError, got %#+v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
rootCertPath := filepath.Join(os.Getenv("PQSSLCERTTEST_PATH"), "root.crt")
|
|
||||||
rootCert := "sslrootcert=" + rootCertPath + " "
|
|
||||||
// No match on Common Name
|
|
||||||
_, err = openSSLConn(t, rootCert+"host=127.0.0.1 sslmode=verify-full user=pqgossltest")
|
|
||||||
if err == nil {
|
|
||||||
t.Fatal("expected error")
|
|
||||||
}
|
|
||||||
_, ok = err.(x509.HostnameError)
|
|
||||||
if !ok {
|
|
||||||
t.Fatalf("expected x509.HostnameError, got %#+v", err)
|
|
||||||
}
|
|
||||||
// OK
|
|
||||||
_, err = openSSLConn(t, rootCert+"host=postgres sslmode=verify-full user=pqgossltest")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test sslmode=verify-ca
|
|
||||||
func TestSSLVerifyCA(t *testing.T) {
|
|
||||||
if shouldSkipSSLTests(t) {
|
|
||||||
t.Log("skipping SSL test")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// Environment sanity check: should fail without SSL
|
|
||||||
checkSSLSetup(t, "sslmode=disable user=pqgossltest")
|
|
||||||
|
|
||||||
// Not OK according to the system CA
|
|
||||||
_, err := openSSLConn(t, "host=postgres sslmode=verify-ca user=pqgossltest")
|
|
||||||
if err == nil {
|
|
||||||
t.Fatal("expected error")
|
|
||||||
}
|
|
||||||
_, ok := err.(x509.UnknownAuthorityError)
|
|
||||||
if !ok {
|
|
||||||
t.Fatalf("expected x509.UnknownAuthorityError, got %#+v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
rootCertPath := filepath.Join(os.Getenv("PQSSLCERTTEST_PATH"), "root.crt")
|
|
||||||
rootCert := "sslrootcert=" + rootCertPath + " "
|
|
||||||
// No match on Common Name, but that's OK
|
|
||||||
_, err = openSSLConn(t, rootCert+"host=127.0.0.1 sslmode=verify-ca user=pqgossltest")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
// Everything OK
|
|
||||||
_, err = openSSLConn(t, rootCert+"host=postgres sslmode=verify-ca user=pqgossltest")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func getCertConninfo(t *testing.T, source string) string {
|
|
||||||
var sslkey string
|
|
||||||
var sslcert string
|
|
||||||
|
|
||||||
certpath := os.Getenv("PQSSLCERTTEST_PATH")
|
|
||||||
|
|
||||||
switch source {
|
|
||||||
case "missingkey":
|
|
||||||
sslkey = "/tmp/filedoesnotexist"
|
|
||||||
sslcert = filepath.Join(certpath, "postgresql.crt")
|
|
||||||
case "missingcert":
|
|
||||||
sslkey = filepath.Join(certpath, "postgresql.key")
|
|
||||||
sslcert = "/tmp/filedoesnotexist"
|
|
||||||
case "certtwice":
|
|
||||||
sslkey = filepath.Join(certpath, "postgresql.crt")
|
|
||||||
sslcert = filepath.Join(certpath, "postgresql.crt")
|
|
||||||
case "valid":
|
|
||||||
sslkey = filepath.Join(certpath, "postgresql.key")
|
|
||||||
sslcert = filepath.Join(certpath, "postgresql.crt")
|
|
||||||
default:
|
|
||||||
t.Fatalf("invalid source %q", source)
|
|
||||||
}
|
|
||||||
return fmt.Sprintf("sslmode=require user=pqgosslcert sslkey=%s sslcert=%s", sslkey, sslcert)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Authenticate over SSL using client certificates
|
|
||||||
func TestSSLClientCertificates(t *testing.T) {
|
|
||||||
if shouldSkipSSLTests(t) {
|
|
||||||
t.Log("skipping SSL test")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// Environment sanity check: should fail without SSL
|
|
||||||
checkSSLSetup(t, "sslmode=disable user=pqgossltest")
|
|
||||||
|
|
||||||
// Should also fail without a valid certificate
|
|
||||||
db, err := openSSLConn(t, "sslmode=require user=pqgosslcert")
|
|
||||||
if err == nil {
|
|
||||||
db.Close()
|
|
||||||
t.Fatal("expected error")
|
|
||||||
}
|
|
||||||
pge, ok := err.(*Error)
|
|
||||||
if !ok {
|
|
||||||
t.Fatal("expected pq.Error")
|
|
||||||
}
|
|
||||||
if pge.Code.Name() != "invalid_authorization_specification" {
|
|
||||||
t.Fatalf("unexpected error code %q", pge.Code.Name())
|
|
||||||
}
|
|
||||||
|
|
||||||
// Should work
|
|
||||||
db, err = openSSLConn(t, getCertConninfo(t, "valid"))
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
rows, err := db.Query("SELECT 1")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
rows.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test errors with ssl certificates
|
|
||||||
func TestSSLClientCertificatesMissingFiles(t *testing.T) {
|
|
||||||
if shouldSkipSSLTests(t) {
|
|
||||||
t.Log("skipping SSL test")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// Environment sanity check: should fail without SSL
|
|
||||||
checkSSLSetup(t, "sslmode=disable user=pqgossltest")
|
|
||||||
|
|
||||||
// Key missing, should fail
|
|
||||||
_, err := openSSLConn(t, getCertConninfo(t, "missingkey"))
|
|
||||||
if err == nil {
|
|
||||||
t.Fatal("expected error")
|
|
||||||
}
|
|
||||||
// should be a PathError
|
|
||||||
_, ok := err.(*os.PathError)
|
|
||||||
if !ok {
|
|
||||||
t.Fatalf("expected PathError, got %#+v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cert missing, should fail
|
|
||||||
_, err = openSSLConn(t, getCertConninfo(t, "missingcert"))
|
|
||||||
if err == nil {
|
|
||||||
t.Fatal("expected error")
|
|
||||||
}
|
|
||||||
// should be a PathError
|
|
||||||
_, ok = err.(*os.PathError)
|
|
||||||
if !ok {
|
|
||||||
t.Fatalf("expected PathError, got %#+v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Key has wrong permissions, should fail
|
|
||||||
_, err = openSSLConn(t, getCertConninfo(t, "certtwice"))
|
|
||||||
if err == nil {
|
|
||||||
t.Fatal("expected error")
|
|
||||||
}
|
|
||||||
if err != ErrSSLKeyHasWorldPermissions {
|
|
||||||
t.Fatalf("expected ErrSSLKeyHasWorldPermissions, got %#+v", err)
|
|
||||||
}
|
|
||||||
}
|
|
54
Godeps/_workspace/src/github.com/lib/pq/url_test.go
generated
vendored
54
Godeps/_workspace/src/github.com/lib/pq/url_test.go
generated
vendored
|
@ -1,54 +0,0 @@
|
||||||
package pq
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestSimpleParseURL(t *testing.T) {
|
|
||||||
expected := "host=hostname.remote"
|
|
||||||
str, err := ParseURL("postgres://hostname.remote")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if str != expected {
|
|
||||||
t.Fatalf("unexpected result from ParseURL:\n+ %v\n- %v", str, expected)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFullParseURL(t *testing.T) {
|
|
||||||
expected := `dbname=database host=hostname.remote password=top\ secret port=1234 user=username`
|
|
||||||
str, err := ParseURL("postgres://username:top%20secret@hostname.remote:1234/database")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if str != expected {
|
|
||||||
t.Fatalf("unexpected result from ParseURL:\n+ %s\n- %s", str, expected)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestInvalidProtocolParseURL(t *testing.T) {
|
|
||||||
_, err := ParseURL("http://hostname.remote")
|
|
||||||
switch err {
|
|
||||||
case nil:
|
|
||||||
t.Fatal("Expected an error from parsing invalid protocol")
|
|
||||||
default:
|
|
||||||
msg := "invalid connection protocol: http"
|
|
||||||
if err.Error() != msg {
|
|
||||||
t.Fatalf("Unexpected error message:\n+ %s\n- %s",
|
|
||||||
err.Error(), msg)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestMinimalURL(t *testing.T) {
|
|
||||||
cs, err := ParseURL("postgres://")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if cs != "" {
|
|
||||||
t.Fatalf("expected blank connection string, got: %q", cs)
|
|
||||||
}
|
|
||||||
}
|
|
119
Godeps/_workspace/src/github.com/mailgun/mailgun-go/acceptance/bounces_test.go
generated
vendored
119
Godeps/_workspace/src/github.com/mailgun/mailgun-go/acceptance/bounces_test.go
generated
vendored
|
@ -1,119 +0,0 @@
|
||||||
// +build acceptance
|
|
||||||
|
|
||||||
package acceptance
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
mailgun "github.com/mailgun/mailgun-go"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestGetBounces(t *testing.T) {
|
|
||||||
domain := reqEnv(t, "MG_DOMAIN")
|
|
||||||
apiKey := reqEnv(t, "MG_API_KEY")
|
|
||||||
mg := mailgun.NewMailgun(domain, apiKey, "")
|
|
||||||
n, bounces, err := mg.GetBounces(-1, -1)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
if n > 0 {
|
|
||||||
t.Fatal("Expected no bounces for what should be a clean domain.")
|
|
||||||
}
|
|
||||||
if n != len(bounces) {
|
|
||||||
t.Fatalf("Expected length of bounces %d to equal returned length %d", len(bounces), n)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestGetSingleBounce(t *testing.T) {
|
|
||||||
domain := reqEnv(t, "MG_DOMAIN")
|
|
||||||
apiKey := reqEnv(t, "MG_API_KEY")
|
|
||||||
mg := mailgun.NewMailgun(domain, apiKey, "")
|
|
||||||
exampleEmail := fmt.Sprintf("baz@%s", domain)
|
|
||||||
_, err := mg.GetSingleBounce(exampleEmail)
|
|
||||||
if err == nil {
|
|
||||||
t.Fatal("Did not expect a bounce to exist")
|
|
||||||
}
|
|
||||||
ure, ok := err.(*mailgun.UnexpectedResponseError)
|
|
||||||
if !ok {
|
|
||||||
t.Fatal("Expected UnexpectedResponseError")
|
|
||||||
}
|
|
||||||
if ure.Actual != 404 {
|
|
||||||
t.Fatalf("Expected 404 response code; got %d", ure.Actual)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestAddDelBounces(t *testing.T) {
|
|
||||||
domain := reqEnv(t, "MG_DOMAIN")
|
|
||||||
apiKey := reqEnv(t, "MG_API_KEY")
|
|
||||||
mg := mailgun.NewMailgun(domain, apiKey, "")
|
|
||||||
|
|
||||||
// Compute an e-mail address for our domain.
|
|
||||||
|
|
||||||
exampleEmail := fmt.Sprintf("baz@%s", domain)
|
|
||||||
|
|
||||||
// First, basic sanity check.
|
|
||||||
// Fail early if we have bounces for a fictitious e-mail address.
|
|
||||||
|
|
||||||
n, _, err := mg.GetBounces(-1, -1)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
if n > 0 {
|
|
||||||
t.Fatal("Expected no bounces for what should be a clean domain.")
|
|
||||||
}
|
|
||||||
|
|
||||||
bounce, err := mg.GetSingleBounce(exampleEmail)
|
|
||||||
if err == nil {
|
|
||||||
t.Fatalf("Expected no bounces for %s", exampleEmail)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add the bounce for our address.
|
|
||||||
|
|
||||||
err = mg.AddBounce(exampleEmail, "550", "TestAddDelBounces-generated error")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// We should now have one bounce listed when we query the API.
|
|
||||||
|
|
||||||
n, bounces, err := mg.GetBounces(-1, -1)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
if n != 1 {
|
|
||||||
t.Fatal("Expected one bounce for this domain.")
|
|
||||||
}
|
|
||||||
if bounces[0].Address != exampleEmail {
|
|
||||||
t.Fatalf("Expected bounce for address %s; got %s", exampleEmail, bounces[0].Address)
|
|
||||||
}
|
|
||||||
|
|
||||||
bounce, err = mg.GetSingleBounce(exampleEmail)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
if bounce.CreatedAt == "" {
|
|
||||||
t.Fatalf("Expected at least one bounce for %s", exampleEmail)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Delete it. This should put us back the way we were.
|
|
||||||
|
|
||||||
err = mg.DeleteBounce(exampleEmail)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make sure we're back to the way we were.
|
|
||||||
|
|
||||||
n, _, err = mg.GetBounces(-1, -1)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
if n > 0 {
|
|
||||||
t.Fatal("Expected no bounces for what should be a clean domain.")
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = mg.GetSingleBounce(exampleEmail)
|
|
||||||
if err == nil {
|
|
||||||
t.Fatalf("Expected no bounces for %s", exampleEmail)
|
|
||||||
}
|
|
||||||
}
|
|
53
Godeps/_workspace/src/github.com/mailgun/mailgun-go/acceptance/credentials_test.go
generated
vendored
53
Godeps/_workspace/src/github.com/mailgun/mailgun-go/acceptance/credentials_test.go
generated
vendored
|
@ -1,53 +0,0 @@
|
||||||
// +build acceptance
|
|
||||||
|
|
||||||
package acceptance
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
mailgun "github.com/mailgun/mailgun-go"
|
|
||||||
"os"
|
|
||||||
"testing"
|
|
||||||
"text/tabwriter"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestGetCredentials(t *testing.T) {
|
|
||||||
domain := reqEnv(t, "MG_DOMAIN")
|
|
||||||
apiKey := reqEnv(t, "MG_API_KEY")
|
|
||||||
mg := mailgun.NewMailgun(domain, apiKey, "")
|
|
||||||
n, cs, err := mg.GetCredentials(mailgun.DefaultLimit, mailgun.DefaultSkip)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
tw := &tabwriter.Writer{}
|
|
||||||
tw.Init(os.Stdout, 2, 8, 2, ' ', 0)
|
|
||||||
fmt.Fprintf(tw, "Login\tCreated At\t\n")
|
|
||||||
for _, c := range cs {
|
|
||||||
fmt.Fprintf(tw, "%s\t%s\t\n", c.Login, c.CreatedAt)
|
|
||||||
}
|
|
||||||
tw.Flush()
|
|
||||||
fmt.Printf("%d credentials listed out of %d\n", len(cs), n)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCreateDeleteCredentials(t *testing.T) {
|
|
||||||
domain := reqEnv(t, "MG_DOMAIN")
|
|
||||||
apiKey := reqEnv(t, "MG_API_KEY")
|
|
||||||
mg := mailgun.NewMailgun(domain, apiKey, "")
|
|
||||||
randomPassword := randomString(16, "pw")
|
|
||||||
randomID := randomString(16, "usr")
|
|
||||||
randomLogin := fmt.Sprintf("%s@%s", randomID, domain)
|
|
||||||
|
|
||||||
err := mg.CreateCredential(randomLogin, randomPassword)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = mg.ChangeCredentialPassword(randomID, randomString(16, "pw2"))
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = mg.DeleteCredential(randomID)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
96
Godeps/_workspace/src/github.com/mailgun/mailgun-go/acceptance/domains_test.go
generated
vendored
96
Godeps/_workspace/src/github.com/mailgun/mailgun-go/acceptance/domains_test.go
generated
vendored
|
@ -1,96 +0,0 @@
|
||||||
// +build acceptance
|
|
||||||
|
|
||||||
package acceptance
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/rand"
|
|
||||||
"fmt"
|
|
||||||
"github.com/mailgun/mailgun-go"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestGetDomains(t *testing.T) {
|
|
||||||
domain := reqEnv(t, "MG_DOMAIN")
|
|
||||||
apiKey := reqEnv(t, "MG_API_KEY")
|
|
||||||
mg := mailgun.NewMailgun(domain, apiKey, "")
|
|
||||||
n, domains, err := mg.GetDomains(mailgun.DefaultLimit, mailgun.DefaultSkip)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
fmt.Printf("TestGetDomains: %d domains retrieved\n", n)
|
|
||||||
for _, d := range domains {
|
|
||||||
fmt.Printf("TestGetDomains: %#v\n", d)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestGetSingleDomain(t *testing.T) {
|
|
||||||
domain := reqEnv(t, "MG_DOMAIN")
|
|
||||||
apiKey := reqEnv(t, "MG_API_KEY")
|
|
||||||
mg := mailgun.NewMailgun(domain, apiKey, "")
|
|
||||||
_, domains, err := mg.GetDomains(mailgun.DefaultLimit, mailgun.DefaultSkip)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
dr, rxDnsRecords, txDnsRecords, err := mg.GetSingleDomain(domains[0].Name)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Printf("TestGetSingleDomain: %#v\n", dr)
|
|
||||||
for _, rxd := range rxDnsRecords {
|
|
||||||
fmt.Printf("TestGetSingleDomains: %#v\n", rxd)
|
|
||||||
}
|
|
||||||
for _, txd := range txDnsRecords {
|
|
||||||
fmt.Printf("TestGetSingleDomains: %#v\n", txd)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestGetSingleDomainNotExist(t *testing.T) {
|
|
||||||
domain := reqEnv(t, "MG_DOMAIN")
|
|
||||||
apiKey := reqEnv(t, "MG_API_KEY")
|
|
||||||
mg := mailgun.NewMailgun(domain, apiKey, "")
|
|
||||||
_, _, _, err := mg.GetSingleDomain(randomString(32, "com.edu.org.") + ".com")
|
|
||||||
if err == nil {
|
|
||||||
t.Fatal("Did not expect a domain to exist")
|
|
||||||
}
|
|
||||||
ure, ok := err.(*mailgun.UnexpectedResponseError)
|
|
||||||
if !ok {
|
|
||||||
t.Fatal("Expected UnexpectedResponseError")
|
|
||||||
}
|
|
||||||
if ure.Actual != 404 {
|
|
||||||
t.Fatalf("Expected 404 response code; got %d", ure.Actual)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestAddDeleteDomain(t *testing.T) {
|
|
||||||
// First, we need to add the domain.
|
|
||||||
domain := reqEnv(t, "MG_DOMAIN")
|
|
||||||
apiKey := reqEnv(t, "MG_API_KEY")
|
|
||||||
mg := mailgun.NewMailgun(domain, apiKey, "")
|
|
||||||
randomDomainName := randomString(16, "DOMAIN") + ".example.com"
|
|
||||||
randomPassword := randomString(16, "PASSWD")
|
|
||||||
err := mg.CreateDomain(randomDomainName, randomPassword, mailgun.Tag, false)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Next, we delete it.
|
|
||||||
err = mg.DeleteDomain(randomDomainName)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// randomString generates a string of given length, but random content.
|
|
||||||
// All content will be within the ASCII graphic character set.
|
|
||||||
// (Implementation from Even Shaw's contribution on
|
|
||||||
// http://stackoverflow.com/questions/12771930/what-is-the-fastest-way-to-generate-a-long-random-string-in-go).
|
|
||||||
func randomString(n int, prefix string) string {
|
|
||||||
const alphanum = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
|
|
||||||
var bytes = make([]byte, n)
|
|
||||||
rand.Read(bytes)
|
|
||||||
for i, b := range bytes {
|
|
||||||
bytes[i] = alphanum[b%byte(len(alphanum))]
|
|
||||||
}
|
|
||||||
return prefix + string(bytes)
|
|
||||||
}
|
|
52
Godeps/_workspace/src/github.com/mailgun/mailgun-go/acceptance/email_validation_test.go
generated
vendored
52
Godeps/_workspace/src/github.com/mailgun/mailgun-go/acceptance/email_validation_test.go
generated
vendored
|
@ -1,52 +0,0 @@
|
||||||
// +build acceptance
|
|
||||||
|
|
||||||
package acceptance
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/mailgun/mailgun-go"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestEmailValidation(t *testing.T) {
|
|
||||||
domain := reqEnv(t, "MG_DOMAIN")
|
|
||||||
apiKey := reqEnv(t, "MG_PUBLIC_API_KEY")
|
|
||||||
mg := mailgun.NewMailgun(domain, "", apiKey)
|
|
||||||
ev, err := mg.ValidateEmail("foo@mailgun.com")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
if ev.IsValid != true {
|
|
||||||
t.Fatal("Expected a valid e-mail address")
|
|
||||||
}
|
|
||||||
if ev.Parts.DisplayName != "" {
|
|
||||||
t.Fatal("No display name should exist")
|
|
||||||
}
|
|
||||||
if ev.Parts.LocalPart != "foo" {
|
|
||||||
t.Fatal("Expected local part of foo; got ", ev.Parts.LocalPart)
|
|
||||||
}
|
|
||||||
if ev.Parts.Domain != "mailgun.com" {
|
|
||||||
t.Fatal("Expected mailgun.com domain; got ", ev.Parts.Domain)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestParseAddresses(t *testing.T) {
|
|
||||||
domain := reqEnv(t, "MG_DOMAIN")
|
|
||||||
apiKey := reqEnv(t, "MG_PUBLIC_API_KEY")
|
|
||||||
mg := mailgun.NewMailgun(domain, "", apiKey)
|
|
||||||
addressesThatParsed, unparsableAddresses, err := mg.ParseAddresses("Alice <alice@example.com>", "bob@example.com", "example.com")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
hittest := map[string]bool{
|
|
||||||
"Alice <alice@example.com>": true,
|
|
||||||
"bob@example.com": true,
|
|
||||||
}
|
|
||||||
for _, a := range addressesThatParsed {
|
|
||||||
if !hittest[a] {
|
|
||||||
t.Fatalf("Expected %s to be parsable", a)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if len(unparsableAddresses) != 1 {
|
|
||||||
t.Fatalf("Expected 1 address to be unparsable; got %d", len(unparsableAddresses))
|
|
||||||
}
|
|
||||||
}
|
|
41
Godeps/_workspace/src/github.com/mailgun/mailgun-go/acceptance/events_test.go
generated
vendored
41
Godeps/_workspace/src/github.com/mailgun/mailgun-go/acceptance/events_test.go
generated
vendored
|
@ -1,41 +0,0 @@
|
||||||
// +build acceptance
|
|
||||||
|
|
||||||
package acceptance
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"github.com/mailgun/mailgun-go"
|
|
||||||
"os"
|
|
||||||
"testing"
|
|
||||||
"text/tabwriter"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestEventIterator(t *testing.T) {
|
|
||||||
// Grab the list of events (as many as we can get)
|
|
||||||
domain := reqEnv(t, "MG_DOMAIN")
|
|
||||||
apiKey := reqEnv(t, "MG_API_KEY")
|
|
||||||
mg := mailgun.NewMailgun(domain, apiKey, "")
|
|
||||||
ei := mg.NewEventIterator()
|
|
||||||
err := ei.GetFirstPage(mailgun.GetEventsOptions{})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Print out the kind of event and timestamp.
|
|
||||||
// Specifics about each event will depend on the "event" type.
|
|
||||||
events := ei.Events()
|
|
||||||
tw := &tabwriter.Writer{}
|
|
||||||
tw.Init(os.Stdout, 2, 8, 2, ' ', tabwriter.AlignRight)
|
|
||||||
fmt.Fprintln(tw, "Event\tTimestamp\t")
|
|
||||||
for _, event := range events {
|
|
||||||
fmt.Fprintf(tw, "%s\t%v\t\n", event["event"], event["timestamp"])
|
|
||||||
}
|
|
||||||
tw.Flush()
|
|
||||||
fmt.Printf("%d events dumped\n\n", len(events))
|
|
||||||
|
|
||||||
// We're on the first page. We must at the beginning.
|
|
||||||
ei.GetPrevious()
|
|
||||||
if len(ei.Events()) != 0 {
|
|
||||||
t.Fatal("Expected to be at the beginning")
|
|
||||||
}
|
|
||||||
}
|
|
205
Godeps/_workspace/src/github.com/mailgun/mailgun-go/acceptance/mailing_lists_test.go
generated
vendored
205
Godeps/_workspace/src/github.com/mailgun/mailgun-go/acceptance/mailing_lists_test.go
generated
vendored
|
@ -1,205 +0,0 @@
|
||||||
// +build acceptance,spendMoney
|
|
||||||
|
|
||||||
package acceptance
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
mailgun "github.com/mailgun/mailgun-go"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func setup(t *testing.T) (mailgun.Mailgun, string) {
|
|
||||||
domain := reqEnv(t, "MG_DOMAIN")
|
|
||||||
apiKey := reqEnv(t, "MG_API_KEY")
|
|
||||||
mg := mailgun.NewMailgun(domain, apiKey, "")
|
|
||||||
|
|
||||||
address := fmt.Sprintf("list5@%s", domain)
|
|
||||||
_, err := mg.CreateList(mailgun.List{
|
|
||||||
Address: address,
|
|
||||||
Name: address,
|
|
||||||
Description: "TestMailingListMembers-related mailing list",
|
|
||||||
AccessLevel: mailgun.Members,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
return mg, address
|
|
||||||
}
|
|
||||||
|
|
||||||
func teardown(t *testing.T, mg mailgun.Mailgun, address string) {
|
|
||||||
err := mg.DeleteList(address)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestMailingListMembers(t *testing.T) {
|
|
||||||
mg, address := setup(t)
|
|
||||||
defer teardown(t, mg, address)
|
|
||||||
|
|
||||||
var countPeople = func() int {
|
|
||||||
n, _, err := mg.GetMembers(mailgun.DefaultLimit, mailgun.DefaultSkip, mailgun.All, address)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
return n
|
|
||||||
}
|
|
||||||
|
|
||||||
startCount := countPeople()
|
|
||||||
protoJoe := mailgun.Member{
|
|
||||||
Address: "joe@example.com",
|
|
||||||
Name: "Joe Example",
|
|
||||||
Subscribed: mailgun.Subscribed,
|
|
||||||
}
|
|
||||||
err := mg.CreateMember(true, address, protoJoe)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
newCount := countPeople()
|
|
||||||
if newCount <= startCount {
|
|
||||||
t.Fatalf("Expected %d people subscribed; got %d", startCount+1, newCount)
|
|
||||||
}
|
|
||||||
|
|
||||||
theMember, err := mg.GetMemberByAddress("joe@example.com", address)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
if (theMember.Address != protoJoe.Address) ||
|
|
||||||
(theMember.Name != protoJoe.Name) ||
|
|
||||||
(*theMember.Subscribed != *protoJoe.Subscribed) ||
|
|
||||||
(len(theMember.Vars) != 0) {
|
|
||||||
t.Fatalf("Unexpected Member: Expected [%#v], Got [%#v]", protoJoe, theMember)
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = mg.UpdateMember("joe@example.com", address, mailgun.Member{
|
|
||||||
Name: "Joe Cool",
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
theMember, err = mg.GetMemberByAddress("joe@example.com", address)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
if theMember.Name != "Joe Cool" {
|
|
||||||
t.Fatal("Expected Joe Cool; got " + theMember.Name)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = mg.DeleteMember("joe@example.com", address)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if countPeople() != startCount {
|
|
||||||
t.Fatalf("Expected %d people; got %d instead", startCount, countPeople())
|
|
||||||
}
|
|
||||||
|
|
||||||
err = mg.CreateMemberList(nil, address, []interface{}{
|
|
||||||
mailgun.Member{
|
|
||||||
Address: "joe.user1@example.com",
|
|
||||||
Name: "Joe's debugging account",
|
|
||||||
Subscribed: mailgun.Unsubscribed,
|
|
||||||
},
|
|
||||||
mailgun.Member{
|
|
||||||
Address: "Joe Cool <joe.user2@example.com>",
|
|
||||||
Name: "Joe's Cool Account",
|
|
||||||
Subscribed: mailgun.Subscribed,
|
|
||||||
},
|
|
||||||
mailgun.Member{
|
|
||||||
Address: "joe.user3@example.com",
|
|
||||||
Vars: map[string]interface{}{
|
|
||||||
"packet-email": "KW9ABC @ BOGBBS-4.#NCA.CA.USA.NOAM",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
theMember, err = mg.GetMemberByAddress("joe.user2@example.com", address)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
if theMember.Name != "Joe's Cool Account" {
|
|
||||||
t.Fatalf("Expected Joe's Cool Account; got %s", theMember.Name)
|
|
||||||
}
|
|
||||||
if theMember.Subscribed != nil {
|
|
||||||
if *theMember.Subscribed != true {
|
|
||||||
t.Fatalf("Expected subscribed to be true; got %v", *theMember.Subscribed)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
t.Fatal("Expected some kind of subscription status; got nil.")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestMailingLists(t *testing.T) {
|
|
||||||
domain := reqEnv(t, "MG_DOMAIN")
|
|
||||||
apiKey := reqEnv(t, "MG_API_KEY")
|
|
||||||
mg := mailgun.NewMailgun(domain, apiKey, "")
|
|
||||||
listAddr := fmt.Sprintf("list2@%s", domain)
|
|
||||||
protoList := mailgun.List{
|
|
||||||
Address: listAddr,
|
|
||||||
Name: "List1",
|
|
||||||
Description: "A list created by an acceptance test.",
|
|
||||||
AccessLevel: mailgun.Members,
|
|
||||||
}
|
|
||||||
|
|
||||||
var countLists = func() int {
|
|
||||||
total, _, err := mg.GetLists(mailgun.DefaultLimit, mailgun.DefaultSkip, "")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
return total
|
|
||||||
}
|
|
||||||
|
|
||||||
startCount := countLists()
|
|
||||||
|
|
||||||
_, err := mg.CreateList(protoList)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
defer func() {
|
|
||||||
err = mg.DeleteList(listAddr)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
newCount := countLists()
|
|
||||||
if newCount != startCount {
|
|
||||||
t.Fatalf("Expected %d lists defined; got %d", startCount, newCount)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
newCount := countLists()
|
|
||||||
if newCount <= startCount {
|
|
||||||
t.Fatalf("Expected %d lists defined; got %d", startCount+1, newCount)
|
|
||||||
}
|
|
||||||
|
|
||||||
theList, err := mg.GetListByAddress(listAddr)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
protoList.CreatedAt = theList.CreatedAt // ignore this field when comparing.
|
|
||||||
if theList != protoList {
|
|
||||||
t.Fatalf("Unexpected list descriptor: Expected [%#v], Got [%#v]", protoList, theList)
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = mg.UpdateList(listAddr, mailgun.List{
|
|
||||||
Description: "A list whose description changed",
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
theList, err = mg.GetListByAddress(listAddr)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
newList := protoList
|
|
||||||
newList.Description = "A list whose description changed"
|
|
||||||
if theList != newList {
|
|
||||||
t.Fatalf("Expected [%#v], Got [%#v]", newList, theList)
|
|
||||||
}
|
|
||||||
}
|
|
329
Godeps/_workspace/src/github.com/mailgun/mailgun-go/acceptance/messages_test.go
generated
vendored
329
Godeps/_workspace/src/github.com/mailgun/mailgun-go/acceptance/messages_test.go
generated
vendored
|
@ -1,329 +0,0 @@
|
||||||
// +build acceptance,spendMoney
|
|
||||||
|
|
||||||
package acceptance
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
mailgun "github.com/mailgun/mailgun-go"
|
|
||||||
"io/ioutil"
|
|
||||||
"strings"
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
fromUser = "=?utf-8?q?Katie_Brewer=2C_CFP=C2=AE?= <joe@example.com>"
|
|
||||||
exampleSubject = "Joe's Example Subject"
|
|
||||||
exampleText = "Testing some Mailgun awesomeness!"
|
|
||||||
exampleHtml = "<html><head /><body><p>Testing some <a href=\"http://google.com?q=abc&r=def&s=ghi\">Mailgun HTML awesomeness!</a> at www.kc5tja@yahoo.com</p></body></html>"
|
|
||||||
|
|
||||||
exampleMime = `Content-Type: text/plain; charset="ascii"
|
|
||||||
Subject: Joe's Example Subject
|
|
||||||
From: Joe Example <joe@example.com>
|
|
||||||
To: BARGLEGARF <sam.falvo@rackspace.com>
|
|
||||||
Content-Transfer-Encoding: 7bit
|
|
||||||
Date: Thu, 6 Mar 2014 00:37:52 +0000
|
|
||||||
|
|
||||||
Testing some Mailgun MIME awesomeness!
|
|
||||||
`
|
|
||||||
templateText = "Greetings %recipient.name%! Your reserved seat is at table %recipient.table%."
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestSendLegacyPlain(t *testing.T) {
|
|
||||||
toUser := reqEnv(t, "MG_EMAIL_TO")
|
|
||||||
domain := reqEnv(t, "MG_DOMAIN")
|
|
||||||
apiKey := reqEnv(t, "MG_API_KEY")
|
|
||||||
publicApiKey := reqEnv(t, "MG_PUBLIC_API_KEY")
|
|
||||||
mg := mailgun.NewMailgun(domain, apiKey, publicApiKey)
|
|
||||||
m := mailgun.NewMessage(fromUser, exampleSubject, exampleText, toUser)
|
|
||||||
msg, id, err := mg.Send(m)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
fmt.Println("TestSendPlain:MSG(" + msg + "),ID(" + id + ")")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSendLegacyPlainWithTracking(t *testing.T) {
|
|
||||||
toUser := reqEnv(t, "MG_EMAIL_TO")
|
|
||||||
domain := reqEnv(t, "MG_DOMAIN")
|
|
||||||
apiKey := reqEnv(t, "MG_API_KEY")
|
|
||||||
publicApiKey := reqEnv(t, "MG_PUBLIC_API_KEY")
|
|
||||||
mg := mailgun.NewMailgun(domain, apiKey, publicApiKey)
|
|
||||||
m := mailgun.NewMessage(fromUser, exampleSubject, exampleText, toUser)
|
|
||||||
m.SetTracking(true)
|
|
||||||
msg, id, err := mg.Send(m)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
fmt.Println("TestSendPlainWithTracking:MSG(" + msg + "),ID(" + id + ")")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSendLegacyPlainAt(t *testing.T) {
|
|
||||||
toUser := reqEnv(t, "MG_EMAIL_TO")
|
|
||||||
domain := reqEnv(t, "MG_DOMAIN")
|
|
||||||
apiKey := reqEnv(t, "MG_API_KEY")
|
|
||||||
publicApiKey := reqEnv(t, "MG_PUBLIC_API_KEY")
|
|
||||||
mg := mailgun.NewMailgun(domain, apiKey, publicApiKey)
|
|
||||||
m := mailgun.NewMessage(fromUser, exampleSubject, exampleText, toUser)
|
|
||||||
m.SetDeliveryTime(time.Now().Add(5 * time.Minute))
|
|
||||||
msg, id, err := mg.Send(m)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
fmt.Println("TestSendPlainAt:MSG(" + msg + "),ID(" + id + ")")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSendLegacyHtml(t *testing.T) {
|
|
||||||
toUser := reqEnv(t, "MG_EMAIL_TO")
|
|
||||||
domain := reqEnv(t, "MG_DOMAIN")
|
|
||||||
apiKey := reqEnv(t, "MG_API_KEY")
|
|
||||||
publicApiKey := reqEnv(t, "MG_PUBLIC_API_KEY")
|
|
||||||
mg := mailgun.NewMailgun(domain, apiKey, publicApiKey)
|
|
||||||
m := mailgun.NewMessage(fromUser, exampleSubject, exampleText, toUser)
|
|
||||||
m.SetHtml(exampleHtml)
|
|
||||||
msg, id, err := mg.Send(m)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
fmt.Println("TestSendHtml:MSG(" + msg + "),ID(" + id + ")")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSendLegacyTracking(t *testing.T) {
|
|
||||||
toUser := reqEnv(t, "MG_EMAIL_TO")
|
|
||||||
domain := reqEnv(t, "MG_DOMAIN")
|
|
||||||
apiKey := reqEnv(t, "MG_API_KEY")
|
|
||||||
publicApiKey := reqEnv(t, "MG_PUBLIC_API_KEY")
|
|
||||||
mg := mailgun.NewMailgun(domain, apiKey, publicApiKey)
|
|
||||||
m := mailgun.NewMessage(fromUser, exampleSubject, exampleText+"Tracking!\n", toUser)
|
|
||||||
m.SetTracking(false)
|
|
||||||
msg, id, err := mg.Send(m)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
fmt.Println("TestSendTracking:MSG(" + msg + "),ID(" + id + ")")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSendLegacyTag(t *testing.T) {
|
|
||||||
toUser := reqEnv(t, "MG_EMAIL_TO")
|
|
||||||
domain := reqEnv(t, "MG_DOMAIN")
|
|
||||||
apiKey := reqEnv(t, "MG_API_KEY")
|
|
||||||
publicApiKey := reqEnv(t, "MG_PUBLIC_API_KEY")
|
|
||||||
mg := mailgun.NewMailgun(domain, apiKey, publicApiKey)
|
|
||||||
m := mailgun.NewMessage(fromUser, exampleSubject, exampleText+"Tags Galore!\n", toUser)
|
|
||||||
m.AddTag("FooTag")
|
|
||||||
m.AddTag("BarTag")
|
|
||||||
m.AddTag("BlortTag")
|
|
||||||
msg, id, err := mg.Send(m)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
fmt.Println("TestSendTag:MSG(" + msg + "),ID(" + id + ")")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSendLegacyMIME(t *testing.T) {
|
|
||||||
toUser := reqEnv(t, "MG_EMAIL_TO")
|
|
||||||
domain := reqEnv(t, "MG_DOMAIN")
|
|
||||||
apiKey := reqEnv(t, "MG_API_KEY")
|
|
||||||
mg := mailgun.NewMailgun(domain, apiKey, "")
|
|
||||||
m := mailgun.NewMIMEMessage(ioutil.NopCloser(strings.NewReader(exampleMime)), toUser)
|
|
||||||
msg, id, err := mg.Send(m)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
fmt.Println("TestSendMIME:MSG(" + msg + "),ID(" + id + ")")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestGetStoredMessage(t *testing.T) {
|
|
||||||
domain := reqEnv(t, "MG_DOMAIN")
|
|
||||||
apiKey := reqEnv(t, "MG_API_KEY")
|
|
||||||
mg := mailgun.NewMailgun(domain, apiKey, "")
|
|
||||||
id, err := findStoredMessageID(mg) // somehow...
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// First, get our stored message.
|
|
||||||
msg, err := mg.GetStoredMessage(id)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
fields := map[string]string{
|
|
||||||
" From": msg.From,
|
|
||||||
" Sender": msg.Sender,
|
|
||||||
" Subject": msg.Subject,
|
|
||||||
"Attachments": fmt.Sprintf("%d", len(msg.Attachments)),
|
|
||||||
" Headers": fmt.Sprintf("%d", len(msg.MessageHeaders)),
|
|
||||||
}
|
|
||||||
for k, v := range fields {
|
|
||||||
fmt.Printf("%13s: %s\n", k, v)
|
|
||||||
}
|
|
||||||
|
|
||||||
// We're done with it; now delete it.
|
|
||||||
err = mg.DeleteStoredMessage(id)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Tries to locate the first stored event type, returning the associated stored message key.
|
|
||||||
func findStoredMessageID(mg mailgun.Mailgun) (string, error) {
|
|
||||||
ei := mg.NewEventIterator()
|
|
||||||
err := ei.GetFirstPage(mailgun.GetEventsOptions{})
|
|
||||||
for {
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
if len(ei.Events()) == 0 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
for _, event := range ei.Events() {
|
|
||||||
if event["event"] == "stored" {
|
|
||||||
s := event["storage"].(map[string]interface{})
|
|
||||||
k := s["key"]
|
|
||||||
return k.(string), nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
err = ei.GetNext()
|
|
||||||
}
|
|
||||||
return "", fmt.Errorf("No stored messages found. Try changing MG_EMAIL_TO to an address that stores messages and try again.")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSendMGPlain(t *testing.T) {
|
|
||||||
toUser := reqEnv(t, "MG_EMAIL_TO")
|
|
||||||
domain := reqEnv(t, "MG_DOMAIN")
|
|
||||||
apiKey := reqEnv(t, "MG_API_KEY")
|
|
||||||
publicApiKey := reqEnv(t, "MG_PUBLIC_API_KEY")
|
|
||||||
mg := mailgun.NewMailgun(domain, apiKey, publicApiKey)
|
|
||||||
m := mg.NewMessage(fromUser, exampleSubject, exampleText, toUser)
|
|
||||||
msg, id, err := mg.Send(m)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
fmt.Println("TestSendPlain:MSG(" + msg + "),ID(" + id + ")")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSendMGPlainWithTracking(t *testing.T) {
|
|
||||||
toUser := reqEnv(t, "MG_EMAIL_TO")
|
|
||||||
domain := reqEnv(t, "MG_DOMAIN")
|
|
||||||
apiKey := reqEnv(t, "MG_API_KEY")
|
|
||||||
publicApiKey := reqEnv(t, "MG_PUBLIC_API_KEY")
|
|
||||||
mg := mailgun.NewMailgun(domain, apiKey, publicApiKey)
|
|
||||||
m := mg.NewMessage(fromUser, exampleSubject, exampleText, toUser)
|
|
||||||
m.SetTracking(true)
|
|
||||||
msg, id, err := mg.Send(m)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
fmt.Println("TestSendPlainWithTracking:MSG(" + msg + "),ID(" + id + ")")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSendMGPlainAt(t *testing.T) {
|
|
||||||
toUser := reqEnv(t, "MG_EMAIL_TO")
|
|
||||||
domain := reqEnv(t, "MG_DOMAIN")
|
|
||||||
apiKey := reqEnv(t, "MG_API_KEY")
|
|
||||||
publicApiKey := reqEnv(t, "MG_PUBLIC_API_KEY")
|
|
||||||
mg := mailgun.NewMailgun(domain, apiKey, publicApiKey)
|
|
||||||
m := mg.NewMessage(fromUser, exampleSubject, exampleText, toUser)
|
|
||||||
m.SetDeliveryTime(time.Now().Add(5 * time.Minute))
|
|
||||||
msg, id, err := mg.Send(m)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
fmt.Println("TestSendPlainAt:MSG(" + msg + "),ID(" + id + ")")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSendMGHtml(t *testing.T) {
|
|
||||||
toUser := reqEnv(t, "MG_EMAIL_TO")
|
|
||||||
domain := reqEnv(t, "MG_DOMAIN")
|
|
||||||
apiKey := reqEnv(t, "MG_API_KEY")
|
|
||||||
publicApiKey := reqEnv(t, "MG_PUBLIC_API_KEY")
|
|
||||||
mg := mailgun.NewMailgun(domain, apiKey, publicApiKey)
|
|
||||||
m := mg.NewMessage(fromUser, exampleSubject, exampleText, toUser)
|
|
||||||
m.SetHtml(exampleHtml)
|
|
||||||
msg, id, err := mg.Send(m)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
fmt.Println("TestSendHtml:MSG(" + msg + "),ID(" + id + ")")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSendMGTracking(t *testing.T) {
|
|
||||||
toUser := reqEnv(t, "MG_EMAIL_TO")
|
|
||||||
domain := reqEnv(t, "MG_DOMAIN")
|
|
||||||
apiKey := reqEnv(t, "MG_API_KEY")
|
|
||||||
publicApiKey := reqEnv(t, "MG_PUBLIC_API_KEY")
|
|
||||||
mg := mailgun.NewMailgun(domain, apiKey, publicApiKey)
|
|
||||||
m := mg.NewMessage(fromUser, exampleSubject, exampleText+"Tracking!\n", toUser)
|
|
||||||
m.SetTracking(false)
|
|
||||||
msg, id, err := mg.Send(m)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
fmt.Println("TestSendTracking:MSG(" + msg + "),ID(" + id + ")")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSendMGTag(t *testing.T) {
|
|
||||||
toUser := reqEnv(t, "MG_EMAIL_TO")
|
|
||||||
domain := reqEnv(t, "MG_DOMAIN")
|
|
||||||
apiKey := reqEnv(t, "MG_API_KEY")
|
|
||||||
publicApiKey := reqEnv(t, "MG_PUBLIC_API_KEY")
|
|
||||||
mg := mailgun.NewMailgun(domain, apiKey, publicApiKey)
|
|
||||||
m := mg.NewMessage(fromUser, exampleSubject, exampleText+"Tags Galore!\n", toUser)
|
|
||||||
m.AddTag("FooTag")
|
|
||||||
m.AddTag("BarTag")
|
|
||||||
m.AddTag("BlortTag")
|
|
||||||
msg, id, err := mg.Send(m)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
fmt.Println("TestSendTag:MSG(" + msg + "),ID(" + id + ")")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSendMGMIME(t *testing.T) {
|
|
||||||
toUser := reqEnv(t, "MG_EMAIL_TO")
|
|
||||||
domain := reqEnv(t, "MG_DOMAIN")
|
|
||||||
apiKey := reqEnv(t, "MG_API_KEY")
|
|
||||||
mg := mailgun.NewMailgun(domain, apiKey, "")
|
|
||||||
m := mg.NewMIMEMessage(ioutil.NopCloser(strings.NewReader(exampleMime)), toUser)
|
|
||||||
msg, id, err := mg.Send(m)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
fmt.Println("TestSendMIME:MSG(" + msg + "),ID(" + id + ")")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSendMGBatchFailRecipients(t *testing.T) {
|
|
||||||
toUser := reqEnv(t, "MG_EMAIL_TO")
|
|
||||||
domain := reqEnv(t, "MG_DOMAIN")
|
|
||||||
apiKey := reqEnv(t, "MG_API_KEY")
|
|
||||||
mg := mailgun.NewMailgun(domain, apiKey, "")
|
|
||||||
m := mg.NewMessage(fromUser, exampleSubject, exampleText+"Batch\n")
|
|
||||||
for i := 0; i < mailgun.MaxNumberOfRecipients; i++ {
|
|
||||||
m.AddRecipient("") // We expect this to indicate a failure at the API
|
|
||||||
}
|
|
||||||
err := m.AddRecipientAndVariables(toUser, nil)
|
|
||||||
if err == nil {
|
|
||||||
// If we're here, either the SDK didn't send the message,
|
|
||||||
// OR the API didn't check for empty To: headers.
|
|
||||||
t.Fatal("Expected to fail!!")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSendMGBatchRecipientVariables(t *testing.T) {
|
|
||||||
toUser := reqEnv(t, "MG_EMAIL_TO")
|
|
||||||
domain := reqEnv(t, "MG_DOMAIN")
|
|
||||||
apiKey := reqEnv(t, "MG_API_KEY")
|
|
||||||
mg := mailgun.NewMailgun(domain, apiKey, "")
|
|
||||||
m := mg.NewMessage(fromUser, exampleSubject, templateText)
|
|
||||||
err := m.AddRecipientAndVariables(toUser, map[string]interface{}{
|
|
||||||
"name": "Joe Cool Example",
|
|
||||||
"table": 42,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
_, _, err = mg.Send(m)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
87
Godeps/_workspace/src/github.com/mailgun/mailgun-go/acceptance/routes_test.go
generated
vendored
87
Godeps/_workspace/src/github.com/mailgun/mailgun-go/acceptance/routes_test.go
generated
vendored
|
@ -1,87 +0,0 @@
|
||||||
// +build acceptance
|
|
||||||
|
|
||||||
package acceptance
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/mailgun/mailgun-go"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestRouteCRUD(t *testing.T) {
|
|
||||||
domain := reqEnv(t, "MG_DOMAIN")
|
|
||||||
apiKey := reqEnv(t, "MG_API_KEY")
|
|
||||||
mg := mailgun.NewMailgun(domain, apiKey, "")
|
|
||||||
|
|
||||||
var countRoutes = func() int {
|
|
||||||
count, _, err := mg.GetRoutes(mailgun.DefaultLimit, mailgun.DefaultSkip)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
return count
|
|
||||||
}
|
|
||||||
|
|
||||||
routeCount := countRoutes()
|
|
||||||
|
|
||||||
newRoute, err := mg.CreateRoute(mailgun.Route{
|
|
||||||
Priority: 1,
|
|
||||||
Description: "Sample Route",
|
|
||||||
Expression: "match_recipient(\".*@samples.mailgun.org\")",
|
|
||||||
Actions: []string{
|
|
||||||
"forward(\"http://example.com/messages/\")",
|
|
||||||
"stop()",
|
|
||||||
},
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
if newRoute.ID == "" {
|
|
||||||
t.Fatal("I expected the route created to have an ID associated with it.")
|
|
||||||
}
|
|
||||||
defer func() {
|
|
||||||
err = mg.DeleteRoute(newRoute.ID)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
newCount := countRoutes()
|
|
||||||
if newCount != routeCount {
|
|
||||||
t.Fatalf("Expected %d routes defined; got %d", routeCount, newCount)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
newCount := countRoutes()
|
|
||||||
if newCount <= routeCount {
|
|
||||||
t.Fatalf("Expected %d routes defined; got %d", routeCount+1, newCount)
|
|
||||||
}
|
|
||||||
|
|
||||||
theRoute, err := mg.GetRouteByID(newRoute.ID)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
if ((newRoute.Priority) != (theRoute.Priority)) ||
|
|
||||||
((newRoute.Description) != (theRoute.Description)) ||
|
|
||||||
((newRoute.Expression) != (theRoute.Expression)) ||
|
|
||||||
(len(newRoute.Actions) != len(theRoute.Actions)) ||
|
|
||||||
((newRoute.CreatedAt) != (theRoute.CreatedAt)) ||
|
|
||||||
((newRoute.ID) != (theRoute.ID)) {
|
|
||||||
t.Fatalf("Expected %#v, got %#v", newRoute, theRoute)
|
|
||||||
}
|
|
||||||
for i, action := range newRoute.Actions {
|
|
||||||
if action != theRoute.Actions[i] {
|
|
||||||
t.Fatalf("Expected %#v, got %#v", newRoute, theRoute)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
changedRoute, err := mg.UpdateRoute(newRoute.ID, mailgun.Route{
|
|
||||||
Priority: 2,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
if changedRoute.Priority != 2 {
|
|
||||||
t.Fatalf("Expected a priority of 2; got %d", changedRoute.Priority)
|
|
||||||
}
|
|
||||||
if len(changedRoute.Actions) != 2 {
|
|
||||||
t.Fatalf("Expected actions to not be touched; got %d entries now", len(changedRoute.Actions))
|
|
||||||
}
|
|
||||||
}
|
|
71
Godeps/_workspace/src/github.com/mailgun/mailgun-go/acceptance/spam_complaints_test.go
generated
vendored
71
Godeps/_workspace/src/github.com/mailgun/mailgun-go/acceptance/spam_complaints_test.go
generated
vendored
|
@ -1,71 +0,0 @@
|
||||||
// +build acceptance
|
|
||||||
|
|
||||||
package acceptance
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/mailgun/mailgun-go"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestGetComplaints(t *testing.T) {
|
|
||||||
domain := reqEnv(t, "MG_DOMAIN")
|
|
||||||
apiKey := reqEnv(t, "MG_API_KEY")
|
|
||||||
publicApiKey := reqEnv(t, "MG_PUBLIC_API_KEY")
|
|
||||||
mg := mailgun.NewMailgun(domain, apiKey, publicApiKey)
|
|
||||||
n, complaints, err := mg.GetComplaints(-1, -1)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
if len(complaints) != n {
|
|
||||||
t.Fatalf("Expected %d complaints; got %d", n, len(complaints))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestGetComplaintFromBazNoComplaint(t *testing.T) {
|
|
||||||
domain := reqEnv(t, "MG_DOMAIN")
|
|
||||||
apiKey := reqEnv(t, "MG_API_KEY")
|
|
||||||
publicApiKey := reqEnv(t, "MG_PUBLIC_API_KEY")
|
|
||||||
mg := mailgun.NewMailgun(domain, apiKey, publicApiKey)
|
|
||||||
_, err := mg.GetSingleComplaint("baz@example.com")
|
|
||||||
if err == nil {
|
|
||||||
t.Fatal("Expected not-found error for missing complaint")
|
|
||||||
}
|
|
||||||
ure, ok := err.(*mailgun.UnexpectedResponseError)
|
|
||||||
if !ok {
|
|
||||||
t.Fatal("Expected UnexpectedResponseError")
|
|
||||||
}
|
|
||||||
if ure.Actual != 404 {
|
|
||||||
t.Fatalf("Expected 404 response code; got %d", ure.Actual)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCreateDeleteComplaint(t *testing.T) {
|
|
||||||
domain := reqEnv(t, "MG_DOMAIN")
|
|
||||||
apiKey := reqEnv(t, "MG_API_KEY")
|
|
||||||
mg := mailgun.NewMailgun(domain, apiKey, "")
|
|
||||||
var check = func(count int) {
|
|
||||||
c, _, err := mg.GetComplaints(mailgun.DefaultLimit, mailgun.DefaultSkip)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
if c != count {
|
|
||||||
t.Fatalf("Expected baz@example.com to have %d complaints; got %d", count, c)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
check(0)
|
|
||||||
|
|
||||||
err := mg.CreateComplaint("baz@example.com")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
check(1)
|
|
||||||
|
|
||||||
err = mg.DeleteComplaint("baz@example.com")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
check(0)
|
|
||||||
}
|
|
40
Godeps/_workspace/src/github.com/mailgun/mailgun-go/acceptance/stats_test.go
generated
vendored
40
Godeps/_workspace/src/github.com/mailgun/mailgun-go/acceptance/stats_test.go
generated
vendored
|
@ -1,40 +0,0 @@
|
||||||
// +build acceptance
|
|
||||||
|
|
||||||
package acceptance
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
mailgun "github.com/mailgun/mailgun-go"
|
|
||||||
"os"
|
|
||||||
"testing"
|
|
||||||
"text/tabwriter"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestGetStats(t *testing.T) {
|
|
||||||
domain := reqEnv(t, "MG_DOMAIN")
|
|
||||||
apiKey := reqEnv(t, "MG_API_KEY")
|
|
||||||
mg := mailgun.NewMailgun(domain, apiKey, "")
|
|
||||||
|
|
||||||
totalCount, stats, err := mg.GetStats(-1, -1, nil, "sent", "opened")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Printf("Total Count: %d\n", totalCount)
|
|
||||||
tw := tabwriter.NewWriter(os.Stdout, 2, 8, 2, ' ', tabwriter.AlignRight)
|
|
||||||
fmt.Fprintf(tw, "Id\tEvent\tCreatedAt\tTotalCount\t\n")
|
|
||||||
for _, stat := range stats {
|
|
||||||
fmt.Fprintf(tw, "%s\t%s\t%s\t%d\t\n", stat.Id, stat.Event, stat.CreatedAt, stat.TotalCount)
|
|
||||||
}
|
|
||||||
tw.Flush()
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestDeleteTag(t *testing.T) {
|
|
||||||
domain := reqEnv(t, "MG_DOMAIN")
|
|
||||||
apiKey := reqEnv(t, "MG_API_KEY")
|
|
||||||
mg := mailgun.NewMailgun(domain, apiKey, "")
|
|
||||||
err := mg.DeleteTag("newsletter")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
71
Godeps/_workspace/src/github.com/mailgun/mailgun-go/acceptance/unsubscribes_test.go
generated
vendored
71
Godeps/_workspace/src/github.com/mailgun/mailgun-go/acceptance/unsubscribes_test.go
generated
vendored
|
@ -1,71 +0,0 @@
|
||||||
// +build acceptance
|
|
||||||
|
|
||||||
package acceptance
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
mailgun "github.com/mailgun/mailgun-go"
|
|
||||||
"os"
|
|
||||||
"testing"
|
|
||||||
"text/tabwriter"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestGetUnsubscribes(t *testing.T) {
|
|
||||||
domain := reqEnv(t, "MG_DOMAIN")
|
|
||||||
apiKey := reqEnv(t, "MG_API_KEY")
|
|
||||||
mg := mailgun.NewMailgun(domain, apiKey, "")
|
|
||||||
n, us, err := mg.GetUnsubscribes(mailgun.DefaultLimit, mailgun.DefaultSkip)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
fmt.Printf("Received %d out of %d unsubscribe records.\n", len(us), n)
|
|
||||||
if len(us) > 0 {
|
|
||||||
tw := &tabwriter.Writer{}
|
|
||||||
tw.Init(os.Stdout, 2, 8, 2, ' ', 0)
|
|
||||||
fmt.Fprintln(tw, "ID\tAddress\tCreated At\tTag\t")
|
|
||||||
for _, u := range us {
|
|
||||||
fmt.Fprintf(tw, "%s\t%s\t%s\t%s\t\n", u.ID, u.Address, u.CreatedAt, u.Tag)
|
|
||||||
}
|
|
||||||
tw.Flush()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestGetUnsubscriptionByAddress(t *testing.T) {
|
|
||||||
domain := reqEnv(t, "MG_DOMAIN")
|
|
||||||
apiKey := reqEnv(t, "MG_API_KEY")
|
|
||||||
email := reqEnv(t, "MG_EMAIL_ADDR")
|
|
||||||
mg := mailgun.NewMailgun(domain, apiKey, "")
|
|
||||||
n, us, err := mg.GetUnsubscribesByAddress(email)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
fmt.Printf("Received %d out of %d unsubscribe records.\n", len(us), n)
|
|
||||||
if len(us) > 0 {
|
|
||||||
tw := &tabwriter.Writer{}
|
|
||||||
tw.Init(os.Stdout, 2, 8, 2, ' ', 0)
|
|
||||||
fmt.Fprintln(tw, "ID\tAddress\tCreated At\tTag\t")
|
|
||||||
for _, u := range us {
|
|
||||||
fmt.Fprintf(tw, "%s\t%s\t%s\t%s\t\n", u.ID, u.Address, u.CreatedAt, u.Tag)
|
|
||||||
}
|
|
||||||
tw.Flush()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCreateDestroyUnsubscription(t *testing.T) {
|
|
||||||
domain := reqEnv(t, "MG_DOMAIN")
|
|
||||||
apiKey := reqEnv(t, "MG_API_KEY")
|
|
||||||
email := reqEnv(t, "MG_EMAIL_ADDR")
|
|
||||||
mg := mailgun.NewMailgun(domain, apiKey, "")
|
|
||||||
|
|
||||||
// Create unsubscription record
|
|
||||||
err := mg.Unsubscribe(email, "*")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Destroy the unsubscription record
|
|
||||||
err = mg.RemoveUnsubscribe(email)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
66
Godeps/_workspace/src/github.com/mailgun/mailgun-go/acceptance/webhooks_test.go
generated
vendored
66
Godeps/_workspace/src/github.com/mailgun/mailgun-go/acceptance/webhooks_test.go
generated
vendored
|
@ -1,66 +0,0 @@
|
||||||
// +build acceptance
|
|
||||||
|
|
||||||
package acceptance
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/mailgun/mailgun-go"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestWebhookCRUD(t *testing.T) {
|
|
||||||
domain := reqEnv(t, "MG_DOMAIN")
|
|
||||||
apiKey := reqEnv(t, "MG_API_KEY")
|
|
||||||
mg := mailgun.NewMailgun(domain, apiKey, "")
|
|
||||||
|
|
||||||
var countHooks = func() int {
|
|
||||||
hooks, err := mg.GetWebhooks()
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
return len(hooks)
|
|
||||||
}
|
|
||||||
|
|
||||||
hookCount := countHooks()
|
|
||||||
|
|
||||||
err := mg.CreateWebhook("deliver", "http://www.example.com")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
defer func() {
|
|
||||||
err = mg.DeleteWebhook("deliver")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
newCount := countHooks()
|
|
||||||
if newCount != hookCount {
|
|
||||||
t.Fatalf("Expected %d routes defined; got %d", hookCount, newCount)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
newCount := countHooks()
|
|
||||||
if newCount <= hookCount {
|
|
||||||
t.Fatalf("Expected %d routes defined; got %d", hookCount+1, newCount)
|
|
||||||
}
|
|
||||||
|
|
||||||
theURL, err := mg.GetWebhookByType("deliver")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
if theURL != "http://www.example.com" {
|
|
||||||
t.Fatalf("Expected http://www.example.com, got %#v", theURL)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = mg.UpdateWebhook("deliver", "http://api.example.com")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
hooks, err := mg.GetWebhooks()
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
if hooks["deliver"] != "http://api.example.com" {
|
|
||||||
t.Fatalf("Expected http://api.example.com, got %#v", hooks["deliver"])
|
|
||||||
}
|
|
||||||
}
|
|
117
Godeps/_workspace/src/github.com/mailgun/mailgun-go/examples_test.go
generated
vendored
117
Godeps/_workspace/src/github.com/mailgun/mailgun-go/examples_test.go
generated
vendored
|
@ -1,117 +0,0 @@
|
||||||
package mailgun
|
|
||||||
|
|
||||||
import (
|
|
||||||
"io/ioutil"
|
|
||||||
"log"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
func ExampleMailgunImpl_ValidateEmail() {
|
|
||||||
mg := NewMailgun("example.com", "", "my_public_api_key")
|
|
||||||
ev, err := mg.ValidateEmail("joe@example.com")
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
if !ev.IsValid {
|
|
||||||
log.Fatal("Expected valid e-mail address")
|
|
||||||
}
|
|
||||||
log.Printf("Parts local_part=%s domain=%s display_name=%s", ev.Parts.LocalPart, ev.Parts.Domain, ev.Parts.DisplayName)
|
|
||||||
if ev.DidYouMean != "" {
|
|
||||||
log.Printf("The address is syntactically valid, but perhaps has a typo.")
|
|
||||||
log.Printf("Did you mean %s instead?", ev.DidYouMean)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func ExampleMailgunImpl_ParseAddresses() {
|
|
||||||
mg := NewMailgun("example.com", "", "my_public_api_key")
|
|
||||||
addressesThatParsed, unparsableAddresses, err := mg.ParseAddresses("Alice <alice@example.com>", "bob@example.com", "example.com")
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
hittest := map[string]bool{
|
|
||||||
"Alice <alice@example.com>": true,
|
|
||||||
"bob@example.com": true,
|
|
||||||
}
|
|
||||||
for _, a := range addressesThatParsed {
|
|
||||||
if !hittest[a] {
|
|
||||||
log.Fatalf("Expected %s to be parsable", a)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if len(unparsableAddresses) != 1 {
|
|
||||||
log.Fatalf("Expected 1 address to be unparsable; got %d", len(unparsableAddresses))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func ExampleMailgunImpl_UpdateList() {
|
|
||||||
mg := NewMailgun("example.com", "my_api_key", "")
|
|
||||||
_, err := mg.UpdateList("joe-stat@example.com", List{
|
|
||||||
Name: "Joe Stat",
|
|
||||||
Description: "Joe's status report list",
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func ExampleMailgunImpl_Send_constructed() {
|
|
||||||
mg := NewMailgun("example.com", "my_api_key", "")
|
|
||||||
m := NewMessage(
|
|
||||||
"Excited User <me@example.com>",
|
|
||||||
"Hello World",
|
|
||||||
"Testing some Mailgun Awesomeness!",
|
|
||||||
"baz@example.com",
|
|
||||||
"bar@example.com",
|
|
||||||
)
|
|
||||||
m.SetTracking(true)
|
|
||||||
m.SetDeliveryTime(time.Now().Add(24 * time.Hour))
|
|
||||||
m.SetHtml("<html><body><h1>Testing some Mailgun Awesomeness!!</h1></body></html>")
|
|
||||||
_, id, err := mg.Send(m)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
log.Printf("Message id=%s", id)
|
|
||||||
}
|
|
||||||
|
|
||||||
func ExampleMailgunImpl_Send_mime() {
|
|
||||||
exampleMime := `Content-Type: text/plain; charset="ascii"
|
|
||||||
Subject: Joe's Example Subject
|
|
||||||
From: Joe Example <joe@example.com>
|
|
||||||
To: BARGLEGARF <bargle.garf@example.com>
|
|
||||||
Content-Transfer-Encoding: 7bit
|
|
||||||
Date: Thu, 6 Mar 2014 00:37:52 +0000
|
|
||||||
|
|
||||||
Testing some Mailgun MIME awesomeness!
|
|
||||||
`
|
|
||||||
mg := NewMailgun("example.com", "my_api_key", "")
|
|
||||||
m := NewMIMEMessage(ioutil.NopCloser(strings.NewReader(exampleMime)), "bargle.garf@example.com")
|
|
||||||
_, id, err := mg.Send(m)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
log.Printf("Message id=%s", id)
|
|
||||||
}
|
|
||||||
|
|
||||||
func ExampleMailgunImpl_GetRoutes() {
|
|
||||||
mg := NewMailgun("example.com", "my_api_key", "")
|
|
||||||
n, routes, err := mg.GetRoutes(DefaultLimit, DefaultSkip)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
if n > len(routes) {
|
|
||||||
log.Printf("More routes exist than has been returned.")
|
|
||||||
}
|
|
||||||
for _, r := range routes {
|
|
||||||
log.Printf("Route pri=%d expr=%s desc=%s", r.Priority, r.Expression, r.Description)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func ExampleMailgunImpl_UpdateRoute() {
|
|
||||||
mg := NewMailgun("example.com", "my_api_key", "")
|
|
||||||
_, err := mg.UpdateRoute("route-id-here", Route{
|
|
||||||
Priority: 2,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
68
Godeps/_workspace/src/github.com/mailgun/mailgun-go/mailgun_test.go
generated
vendored
68
Godeps/_workspace/src/github.com/mailgun/mailgun-go/mailgun_test.go
generated
vendored
|
@ -1,68 +0,0 @@
|
||||||
package mailgun
|
|
||||||
|
|
||||||
import (
|
|
||||||
"strconv"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
const domain = "valid-mailgun-domain"
|
|
||||||
const apiKey = "valid-mailgun-api-key"
|
|
||||||
const publicApiKey = "valid-mailgun-public-api-key"
|
|
||||||
|
|
||||||
func TestMailgun(t *testing.T) {
|
|
||||||
m := NewMailgun(domain, apiKey, publicApiKey)
|
|
||||||
|
|
||||||
if domain != m.Domain() {
|
|
||||||
t.Fatal("Domain not equal!")
|
|
||||||
}
|
|
||||||
|
|
||||||
if apiKey != m.ApiKey() {
|
|
||||||
t.Fatal("ApiKey not equal!")
|
|
||||||
}
|
|
||||||
|
|
||||||
if publicApiKey != m.PublicApiKey() {
|
|
||||||
t.Fatal("PublicApiKey not equal!")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestBounceGetCode(t *testing.T) {
|
|
||||||
b1 := &Bounce{
|
|
||||||
CreatedAt: "blah",
|
|
||||||
code: 123,
|
|
||||||
Address: "blort",
|
|
||||||
Error: "bletch",
|
|
||||||
}
|
|
||||||
c, err := b1.GetCode()
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
if c != 123 {
|
|
||||||
t.Fatal("Expected 123; got ", c)
|
|
||||||
}
|
|
||||||
|
|
||||||
b2 := &Bounce{
|
|
||||||
CreatedAt: "blah",
|
|
||||||
code: "456",
|
|
||||||
Address: "blort",
|
|
||||||
Error: "Bletch",
|
|
||||||
}
|
|
||||||
c, err = b2.GetCode()
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
if c != 456 {
|
|
||||||
t.Fatal("Expected 456; got ", c)
|
|
||||||
}
|
|
||||||
|
|
||||||
b3 := &Bounce{
|
|
||||||
CreatedAt: "blah",
|
|
||||||
code: "456H",
|
|
||||||
Address: "blort",
|
|
||||||
Error: "Bletch",
|
|
||||||
}
|
|
||||||
c, err = b3.GetCode()
|
|
||||||
e, ok := err.(*strconv.NumError)
|
|
||||||
if !ok && e != nil {
|
|
||||||
t.Fatal("Expected a syntax error in numeric conversion: got ", err)
|
|
||||||
}
|
|
||||||
}
|
|
133
Godeps/_workspace/src/github.com/mbanzon/simplehttp/helpers_test.go
generated
vendored
133
Godeps/_workspace/src/github.com/mbanzon/simplehttp/helpers_test.go
generated
vendored
|
@ -1,133 +0,0 @@
|
||||||
package simplehttp
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"encoding/xml"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestParsingGetFromJson(t *testing.T) {
|
|
||||||
tmp := testStruct{
|
|
||||||
Value1: "1",
|
|
||||||
Value2: "2",
|
|
||||||
Value3: "3",
|
|
||||||
}
|
|
||||||
|
|
||||||
data, err := json.Marshal(tmp)
|
|
||||||
if err != nil {
|
|
||||||
t.Fail()
|
|
||||||
}
|
|
||||||
|
|
||||||
server.SetNextResponse(data)
|
|
||||||
|
|
||||||
request := NewHTTPRequest(dummyurl)
|
|
||||||
var retVal testStruct
|
|
||||||
err = request.GetResponseFromJSON(&retVal)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
t.Fail()
|
|
||||||
}
|
|
||||||
|
|
||||||
if tmp.Value1 != retVal.Value1 {
|
|
||||||
t.Fail()
|
|
||||||
}
|
|
||||||
|
|
||||||
if tmp.Value2 != retVal.Value2 {
|
|
||||||
t.Fail()
|
|
||||||
}
|
|
||||||
|
|
||||||
if tmp.Value3 != retVal.Value3 {
|
|
||||||
t.Fail()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFailingParsingGetFromJson(t *testing.T) {
|
|
||||||
request := NewHTTPRequest(invalidurl)
|
|
||||||
var retVal testStruct
|
|
||||||
err := request.GetResponseFromJSON(&retVal)
|
|
||||||
|
|
||||||
if err == nil {
|
|
||||||
t.Fail()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestParsingPostFromJson(t *testing.T) {
|
|
||||||
tmp := testStruct{
|
|
||||||
Value1: "1",
|
|
||||||
Value2: "2",
|
|
||||||
Value3: "3",
|
|
||||||
}
|
|
||||||
|
|
||||||
data, err := json.Marshal(tmp)
|
|
||||||
if err != nil {
|
|
||||||
t.Fail()
|
|
||||||
}
|
|
||||||
|
|
||||||
server.SetNextResponse(data)
|
|
||||||
|
|
||||||
request := NewHTTPRequest(dummyurl)
|
|
||||||
var retVal testStruct
|
|
||||||
err = request.PostResponseFromJSON(nil, &retVal)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
t.Fail()
|
|
||||||
}
|
|
||||||
|
|
||||||
if tmp.Value1 != retVal.Value1 {
|
|
||||||
t.Fail()
|
|
||||||
}
|
|
||||||
|
|
||||||
if tmp.Value2 != retVal.Value2 {
|
|
||||||
t.Fail()
|
|
||||||
}
|
|
||||||
|
|
||||||
if tmp.Value3 != retVal.Value3 {
|
|
||||||
t.Fail()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFailingParsingPostFromJson(t *testing.T) {
|
|
||||||
request := NewHTTPRequest(invalidurl)
|
|
||||||
var retVal testStruct
|
|
||||||
err := request.PostResponseFromJSON(nil, &retVal)
|
|
||||||
|
|
||||||
if err == nil {
|
|
||||||
t.Fail()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestParsingGetFromXml(t *testing.T) {
|
|
||||||
tmp := testStruct{
|
|
||||||
Value1: "1",
|
|
||||||
Value2: "2",
|
|
||||||
Value3: "3",
|
|
||||||
}
|
|
||||||
|
|
||||||
data, err := xml.Marshal(tmp)
|
|
||||||
if err != nil {
|
|
||||||
t.Fail()
|
|
||||||
}
|
|
||||||
|
|
||||||
server.SetNextResponse(data)
|
|
||||||
|
|
||||||
request := NewHTTPRequest(dummyurl)
|
|
||||||
var retVal testStruct
|
|
||||||
response, err := request.MakeGetRequest()
|
|
||||||
response.ParseFromXML(&retVal)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
t.Fail()
|
|
||||||
}
|
|
||||||
|
|
||||||
if tmp.Value1 != retVal.Value1 {
|
|
||||||
t.Fail()
|
|
||||||
}
|
|
||||||
|
|
||||||
if tmp.Value2 != retVal.Value2 {
|
|
||||||
t.Fail()
|
|
||||||
}
|
|
||||||
|
|
||||||
if tmp.Value3 != retVal.Value3 {
|
|
||||||
t.Fail()
|
|
||||||
}
|
|
||||||
}
|
|
38
Godeps/_workspace/src/github.com/mbanzon/simplehttp/payload_test.go
generated
vendored
38
Godeps/_workspace/src/github.com/mbanzon/simplehttp/payload_test.go
generated
vendored
|
@ -1,38 +0,0 @@
|
||||||
package simplehttp
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"github.com/mbanzon/callbackenv"
|
|
||||||
"io/ioutil"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
FILE_ENV = "SIMPLEHTTP_TEST_FILE"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestFormDataPayloadPost(t *testing.T) {
|
|
||||||
payload := NewFormDataPayload()
|
|
||||||
payload.AddValue("key", "value")
|
|
||||||
|
|
||||||
buf := &bytes.Buffer{}
|
|
||||||
buf.Write([]byte("testing testing testing"))
|
|
||||||
|
|
||||||
rc := ioutil.NopCloser(buf)
|
|
||||||
payload.AddReadCloser("foo", "bar", rc)
|
|
||||||
|
|
||||||
callbackenv.RequireEnv(FILE_ENV,
|
|
||||||
func(file string) {
|
|
||||||
payload.AddFile("file", file)
|
|
||||||
}, nil)
|
|
||||||
|
|
||||||
request := NewHTTPRequest(dummyurl)
|
|
||||||
request.MakePostRequest(payload)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestUrlEncodedPayloadPost(t *testing.T) {
|
|
||||||
payload := NewUrlEncodedPayload()
|
|
||||||
payload.AddValue("key", "value")
|
|
||||||
request := NewHTTPRequest(dummyurl)
|
|
||||||
request.MakePostRequest(payload)
|
|
||||||
}
|
|
104
Godeps/_workspace/src/github.com/mbanzon/simplehttp/shorthand_test.go
generated
vendored
104
Godeps/_workspace/src/github.com/mbanzon/simplehttp/shorthand_test.go
generated
vendored
|
@ -1,104 +0,0 @@
|
||||||
package simplehttp
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestShorthandFailingPayload(t *testing.T) {
|
|
||||||
Request{
|
|
||||||
Url: dummyurl,
|
|
||||||
Data: nil,
|
|
||||||
}.Post()
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestShorthandGet(t *testing.T) {
|
|
||||||
code, _, err := Request{
|
|
||||||
Url: dummyurl,
|
|
||||||
UserAgent: "simplehttp go test",
|
|
||||||
}.Get()
|
|
||||||
|
|
||||||
if code == -1 || err != nil {
|
|
||||||
t.Fail()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestShorthandPost(t *testing.T) {
|
|
||||||
code, _, err := Request{
|
|
||||||
Url: dummyurl,
|
|
||||||
Data: []byte("foobar"),
|
|
||||||
UserAgent: "simplehttp go test",
|
|
||||||
Authentication: BasicAuthentication{
|
|
||||||
User: "test",
|
|
||||||
Password: "test",
|
|
||||||
},
|
|
||||||
}.Post()
|
|
||||||
|
|
||||||
if code == -1 || err != nil {
|
|
||||||
t.Fail()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestShorthandPut(t *testing.T) {
|
|
||||||
code, _, err := Request{
|
|
||||||
Url: dummyurl,
|
|
||||||
Data: []byte("foobar"),
|
|
||||||
UserAgent: "simplehttp go test",
|
|
||||||
}.Put()
|
|
||||||
|
|
||||||
if code == -1 || err != nil {
|
|
||||||
t.Fail()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestShorthandDelete(t *testing.T) {
|
|
||||||
code, _, err := Request{
|
|
||||||
Url: dummyurl,
|
|
||||||
UserAgent: "simplehttp go test",
|
|
||||||
}.Delete()
|
|
||||||
|
|
||||||
if code == -1 || err != nil {
|
|
||||||
t.Fail()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFailingShorthandGet(t *testing.T) {
|
|
||||||
code, _, err := Request{
|
|
||||||
Url: invalidurl,
|
|
||||||
}.Get()
|
|
||||||
|
|
||||||
if code != -1 || err == nil {
|
|
||||||
t.Fail()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFailingShorthandPost(t *testing.T) {
|
|
||||||
code, _, err := Request{
|
|
||||||
Url: invalidurl,
|
|
||||||
Data: []byte("foobar"),
|
|
||||||
}.Post()
|
|
||||||
|
|
||||||
if code != -1 || err == nil {
|
|
||||||
t.Fail()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFailingShorthandPut(t *testing.T) {
|
|
||||||
code, _, err := Request{
|
|
||||||
Url: invalidurl,
|
|
||||||
Data: []byte("foobar"),
|
|
||||||
}.Put()
|
|
||||||
|
|
||||||
if code != -1 || err == nil {
|
|
||||||
t.Fail()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFailingShorthandDelete(t *testing.T) {
|
|
||||||
code, _, err := Request{
|
|
||||||
Url: invalidurl,
|
|
||||||
}.Delete()
|
|
||||||
|
|
||||||
if code != -1 || err == nil {
|
|
||||||
t.Fail()
|
|
||||||
}
|
|
||||||
}
|
|
37
Godeps/_workspace/src/github.com/mbanzon/simplehttp/simplehttp_test.go
generated
vendored
37
Godeps/_workspace/src/github.com/mbanzon/simplehttp/simplehttp_test.go
generated
vendored
|
@ -1,37 +0,0 @@
|
||||||
package simplehttp
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/mbanzon/dummyserver"
|
|
||||||
"log"
|
|
||||||
"strconv"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
server *dummyserver.DummyServer
|
|
||||||
dummyurl string
|
|
||||||
invalidurl string
|
|
||||||
)
|
|
||||||
|
|
||||||
type testStruct struct {
|
|
||||||
Value1 string `json:"value1" xml:"value1"`
|
|
||||||
Value2 string `json:"value2" xml:"value2"`
|
|
||||||
Value3 string `json:"value3" xml:"value3"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
server = dummyserver.NewRandomServer()
|
|
||||||
go func() {
|
|
||||||
err := server.Start()
|
|
||||||
log.Fatal(err)
|
|
||||||
}()
|
|
||||||
dummyurl = "http://localhost:" + strconv.Itoa(server.GetPort()) + "/"
|
|
||||||
invalidurl = "invalid://invalid"
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestAddParameters(t *testing.T) {
|
|
||||||
request := NewHTTPRequest(dummyurl)
|
|
||||||
request.AddParameter("p1", "v1")
|
|
||||||
|
|
||||||
request.MakeGetRequest()
|
|
||||||
}
|
|
136
Godeps/_workspace/src/github.com/rubenv/sql-migrate/bindata_test.go
generated
vendored
136
Godeps/_workspace/src/github.com/rubenv/sql-migrate/bindata_test.go
generated
vendored
|
@ -1,136 +0,0 @@
|
||||||
package migrate
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"compress/gzip"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
func bindata_read(data []byte, name string) ([]byte, error) {
|
|
||||||
gz, err := gzip.NewReader(bytes.NewBuffer(data))
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("Read %q: %v", name, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
var buf bytes.Buffer
|
|
||||||
_, err = io.Copy(&buf, gz)
|
|
||||||
gz.Close()
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("Read %q: %v", name, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return buf.Bytes(), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func test_migrations_1_initial_sql() ([]byte, error) {
|
|
||||||
return bindata_read([]byte{
|
|
||||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x00, 0xff, 0x8c, 0xcd,
|
|
||||||
0x3d, 0x0e, 0x82, 0x40, 0x10, 0x05, 0xe0, 0x7e, 0x4e, 0xf1, 0x3a, 0x34,
|
|
||||||
0x86, 0x13, 0x50, 0xa1, 0xd0, 0x91, 0xa8, 0x08, 0x07, 0x40, 0x76, 0x22,
|
|
||||||
0x13, 0xd7, 0xdd, 0x09, 0xac, 0xc1, 0xe3, 0xbb, 0xc4, 0x68, 0xb4, 0xb3,
|
|
||||||
0x7c, 0x6f, 0x7e, 0xbe, 0x34, 0xc5, 0xe6, 0x26, 0x97, 0xb1, 0x0b, 0x8c,
|
|
||||||
0x56, 0x29, 0xc6, 0xd3, 0xb1, 0x82, 0x38, 0x4c, 0xdc, 0x07, 0xf1, 0x0e,
|
|
||||||
0x49, 0xab, 0x09, 0x64, 0x02, 0x3f, 0xb8, 0xbf, 0x07, 0x36, 0x98, 0x07,
|
|
||||||
0x76, 0x08, 0x43, 0xac, 0x5e, 0x77, 0xcb, 0x52, 0x0c, 0x9d, 0xaa, 0x15,
|
|
||||||
0x36, 0xb4, 0xab, 0xcb, 0xbc, 0x29, 0xd1, 0xe4, 0xdb, 0xaa, 0x84, 0xb2,
|
|
||||||
0x57, 0xcb, 0x58, 0x89, 0x89, 0x2f, 0xc3, 0x3a, 0x23, 0xa2, 0x6f, 0xb0,
|
|
||||||
0xf0, 0xb3, 0x7b, 0x93, 0x1f, 0x6f, 0x29, 0xff, 0x12, 0x47, 0x6f, 0x6d,
|
|
||||||
0x9c, 0x9e, 0xbb, 0xfe, 0x4a, 0x45, 0xbd, 0x3f, 0xfc, 0x98, 0x19, 0x3d,
|
|
||||||
0x03, 0x00, 0x00, 0xff, 0xff, 0x0d, 0x70, 0x5e, 0xf9, 0xda, 0x00, 0x00,
|
|
||||||
0x00,
|
|
||||||
},
|
|
||||||
"test-migrations/1_initial.sql",
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
func test_migrations_2_record_sql() ([]byte, error) {
|
|
||||||
return bindata_read([]byte{
|
|
||||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x00, 0xff, 0xd2, 0xd5,
|
|
||||||
0x55, 0xd0, 0xce, 0xcd, 0x4c, 0x2f, 0x4a, 0x2c, 0x49, 0x55, 0x08, 0x2d,
|
|
||||||
0xe0, 0xf2, 0xf4, 0x0b, 0x76, 0x0d, 0x0a, 0x51, 0xf0, 0xf4, 0x0b, 0xf1,
|
|
||||||
0x57, 0x28, 0x48, 0xcd, 0x2f, 0xc8, 0x49, 0x55, 0xd0, 0xc8, 0x4c, 0xd1,
|
|
||||||
0x54, 0x08, 0x73, 0xf4, 0x09, 0x75, 0x0d, 0x56, 0xd0, 0x30, 0xd4, 0xb4,
|
|
||||||
0xe6, 0xe2, 0x42, 0xd6, 0xe3, 0x92, 0x5f, 0x9e, 0xc7, 0xe5, 0xe2, 0xea,
|
|
||||||
0xe3, 0x1a, 0xe2, 0xaa, 0xe0, 0x16, 0xe4, 0xef, 0x0b, 0xd3, 0x15, 0xee,
|
|
||||||
0xe1, 0x1a, 0xe4, 0xaa, 0x90, 0x99, 0x62, 0x6b, 0x68, 0xcd, 0x05, 0x08,
|
|
||||||
0x00, 0x00, 0xff, 0xff, 0xf4, 0x3a, 0x7b, 0xae, 0x64, 0x00, 0x00, 0x00,
|
|
||||||
},
|
|
||||||
"test-migrations/2_record.sql",
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Asset loads and returns the asset for the given name.
|
|
||||||
// It returns an error if the asset could not be found or
|
|
||||||
// could not be loaded.
|
|
||||||
func Asset(name string) ([]byte, error) {
|
|
||||||
cannonicalName := strings.Replace(name, "\\", "/", -1)
|
|
||||||
if f, ok := _bindata[cannonicalName]; ok {
|
|
||||||
return f()
|
|
||||||
}
|
|
||||||
return nil, fmt.Errorf("Asset %s not found", name)
|
|
||||||
}
|
|
||||||
|
|
||||||
// AssetNames returns the names of the assets.
|
|
||||||
func AssetNames() []string {
|
|
||||||
names := make([]string, 0, len(_bindata))
|
|
||||||
for name := range _bindata {
|
|
||||||
names = append(names, name)
|
|
||||||
}
|
|
||||||
return names
|
|
||||||
}
|
|
||||||
|
|
||||||
// _bindata is a table, holding each asset generator, mapped to its name.
|
|
||||||
var _bindata = map[string]func() ([]byte, error){
|
|
||||||
"test-migrations/1_initial.sql": test_migrations_1_initial_sql,
|
|
||||||
"test-migrations/2_record.sql": test_migrations_2_record_sql,
|
|
||||||
}
|
|
||||||
// AssetDir returns the file names below a certain
|
|
||||||
// directory embedded in the file by go-bindata.
|
|
||||||
// For example if you run go-bindata on data/... and data contains the
|
|
||||||
// following hierarchy:
|
|
||||||
// data/
|
|
||||||
// foo.txt
|
|
||||||
// img/
|
|
||||||
// a.png
|
|
||||||
// b.png
|
|
||||||
// then AssetDir("data") would return []string{"foo.txt", "img"}
|
|
||||||
// AssetDir("data/img") would return []string{"a.png", "b.png"}
|
|
||||||
// AssetDir("foo.txt") and AssetDir("notexist") would return an error
|
|
||||||
// AssetDir("") will return []string{"data"}.
|
|
||||||
func AssetDir(name string) ([]string, error) {
|
|
||||||
node := _bintree
|
|
||||||
if len(name) != 0 {
|
|
||||||
cannonicalName := strings.Replace(name, "\\", "/", -1)
|
|
||||||
pathList := strings.Split(cannonicalName, "/")
|
|
||||||
for _, p := range pathList {
|
|
||||||
node = node.Children[p]
|
|
||||||
if node == nil {
|
|
||||||
return nil, fmt.Errorf("Asset %s not found", name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if node.Func != nil {
|
|
||||||
return nil, fmt.Errorf("Asset %s not found", name)
|
|
||||||
}
|
|
||||||
rv := make([]string, 0, len(node.Children))
|
|
||||||
for name := range node.Children {
|
|
||||||
rv = append(rv, name)
|
|
||||||
}
|
|
||||||
return rv, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type _bintree_t struct {
|
|
||||||
Func func() ([]byte, error)
|
|
||||||
Children map[string]*_bintree_t
|
|
||||||
}
|
|
||||||
var _bintree = &_bintree_t{nil, map[string]*_bintree_t{
|
|
||||||
"test-migrations": &_bintree_t{nil, map[string]*_bintree_t{
|
|
||||||
"1_initial.sql": &_bintree_t{test_migrations_1_initial_sql, map[string]*_bintree_t{
|
|
||||||
}},
|
|
||||||
"2_record.sql": &_bintree_t{test_migrations_2_record_sql, map[string]*_bintree_t{
|
|
||||||
}},
|
|
||||||
}},
|
|
||||||
}}
|
|
9
Godeps/_workspace/src/github.com/rubenv/sql-migrate/init_test.go
generated
vendored
9
Godeps/_workspace/src/github.com/rubenv/sql-migrate/init_test.go
generated
vendored
|
@ -1,9 +0,0 @@
|
||||||
package migrate
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
. "gopkg.in/check.v1"
|
|
||||||
)
|
|
||||||
|
|
||||||
func Test(t *testing.T) { TestingT(t) }
|
|
357
Godeps/_workspace/src/github.com/rubenv/sql-migrate/migrate_test.go
generated
vendored
357
Godeps/_workspace/src/github.com/rubenv/sql-migrate/migrate_test.go
generated
vendored
|
@ -1,357 +0,0 @@
|
||||||
package migrate
|
|
||||||
|
|
||||||
import (
|
|
||||||
"database/sql"
|
|
||||||
"os"
|
|
||||||
|
|
||||||
_ "github.com/mattn/go-sqlite3"
|
|
||||||
. "gopkg.in/check.v1"
|
|
||||||
"gopkg.in/gorp.v1"
|
|
||||||
)
|
|
||||||
|
|
||||||
var filename = "/tmp/sql-migrate-sqlite.db"
|
|
||||||
var sqliteMigrations = []*Migration{
|
|
||||||
&Migration{
|
|
||||||
Id: "123",
|
|
||||||
Up: []string{"CREATE TABLE people (id int)"},
|
|
||||||
Down: []string{"DROP TABLE people"},
|
|
||||||
},
|
|
||||||
&Migration{
|
|
||||||
Id: "124",
|
|
||||||
Up: []string{"ALTER TABLE people ADD COLUMN first_name text"},
|
|
||||||
Down: []string{"SELECT 0"}, // Not really supported
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
type SqliteMigrateSuite struct {
|
|
||||||
Db *sql.DB
|
|
||||||
DbMap *gorp.DbMap
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ = Suite(&SqliteMigrateSuite{})
|
|
||||||
|
|
||||||
func (s *SqliteMigrateSuite) SetUpTest(c *C) {
|
|
||||||
db, err := sql.Open("sqlite3", filename)
|
|
||||||
c.Assert(err, IsNil)
|
|
||||||
|
|
||||||
s.Db = db
|
|
||||||
s.DbMap = &gorp.DbMap{Db: db, Dialect: &gorp.SqliteDialect{}}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *SqliteMigrateSuite) TearDownTest(c *C) {
|
|
||||||
err := os.Remove(filename)
|
|
||||||
c.Assert(err, IsNil)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *SqliteMigrateSuite) TestRunMigration(c *C) {
|
|
||||||
migrations := &MemoryMigrationSource{
|
|
||||||
Migrations: sqliteMigrations[:1],
|
|
||||||
}
|
|
||||||
|
|
||||||
// Executes one migration
|
|
||||||
n, err := Exec(s.Db, "sqlite3", migrations, Up)
|
|
||||||
c.Assert(err, IsNil)
|
|
||||||
c.Assert(n, Equals, 1)
|
|
||||||
|
|
||||||
// Can use table now
|
|
||||||
_, err = s.DbMap.Exec("SELECT * FROM people")
|
|
||||||
c.Assert(err, IsNil)
|
|
||||||
|
|
||||||
// Shouldn't apply migration again
|
|
||||||
n, err = Exec(s.Db, "sqlite3", migrations, Up)
|
|
||||||
c.Assert(err, IsNil)
|
|
||||||
c.Assert(n, Equals, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *SqliteMigrateSuite) TestMigrateMultiple(c *C) {
|
|
||||||
migrations := &MemoryMigrationSource{
|
|
||||||
Migrations: sqliteMigrations[:2],
|
|
||||||
}
|
|
||||||
|
|
||||||
// Executes two migrations
|
|
||||||
n, err := Exec(s.Db, "sqlite3", migrations, Up)
|
|
||||||
c.Assert(err, IsNil)
|
|
||||||
c.Assert(n, Equals, 2)
|
|
||||||
|
|
||||||
// Can use column now
|
|
||||||
_, err = s.DbMap.Exec("SELECT first_name FROM people")
|
|
||||||
c.Assert(err, IsNil)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *SqliteMigrateSuite) TestMigrateIncremental(c *C) {
|
|
||||||
migrations := &MemoryMigrationSource{
|
|
||||||
Migrations: sqliteMigrations[:1],
|
|
||||||
}
|
|
||||||
|
|
||||||
// Executes one migration
|
|
||||||
n, err := Exec(s.Db, "sqlite3", migrations, Up)
|
|
||||||
c.Assert(err, IsNil)
|
|
||||||
c.Assert(n, Equals, 1)
|
|
||||||
|
|
||||||
// Execute a new migration
|
|
||||||
migrations = &MemoryMigrationSource{
|
|
||||||
Migrations: sqliteMigrations[:2],
|
|
||||||
}
|
|
||||||
n, err = Exec(s.Db, "sqlite3", migrations, Up)
|
|
||||||
c.Assert(err, IsNil)
|
|
||||||
c.Assert(n, Equals, 1)
|
|
||||||
|
|
||||||
// Can use column now
|
|
||||||
_, err = s.DbMap.Exec("SELECT first_name FROM people")
|
|
||||||
c.Assert(err, IsNil)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *SqliteMigrateSuite) TestFileMigrate(c *C) {
|
|
||||||
migrations := &FileMigrationSource{
|
|
||||||
Dir: "test-migrations",
|
|
||||||
}
|
|
||||||
|
|
||||||
// Executes two migrations
|
|
||||||
n, err := Exec(s.Db, "sqlite3", migrations, Up)
|
|
||||||
c.Assert(err, IsNil)
|
|
||||||
c.Assert(n, Equals, 2)
|
|
||||||
|
|
||||||
// Has data
|
|
||||||
id, err := s.DbMap.SelectInt("SELECT id FROM people")
|
|
||||||
c.Assert(err, IsNil)
|
|
||||||
c.Assert(id, Equals, int64(1))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *SqliteMigrateSuite) TestAssetMigrate(c *C) {
|
|
||||||
migrations := &AssetMigrationSource{
|
|
||||||
Asset: Asset,
|
|
||||||
AssetDir: AssetDir,
|
|
||||||
Dir: "test-migrations",
|
|
||||||
}
|
|
||||||
|
|
||||||
// Executes two migrations
|
|
||||||
n, err := Exec(s.Db, "sqlite3", migrations, Up)
|
|
||||||
c.Assert(err, IsNil)
|
|
||||||
c.Assert(n, Equals, 2)
|
|
||||||
|
|
||||||
// Has data
|
|
||||||
id, err := s.DbMap.SelectInt("SELECT id FROM people")
|
|
||||||
c.Assert(err, IsNil)
|
|
||||||
c.Assert(id, Equals, int64(1))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *SqliteMigrateSuite) TestMigrateMax(c *C) {
|
|
||||||
migrations := &FileMigrationSource{
|
|
||||||
Dir: "test-migrations",
|
|
||||||
}
|
|
||||||
|
|
||||||
// Executes one migration
|
|
||||||
n, err := ExecMax(s.Db, "sqlite3", migrations, Up, 1)
|
|
||||||
c.Assert(err, IsNil)
|
|
||||||
c.Assert(n, Equals, 1)
|
|
||||||
|
|
||||||
id, err := s.DbMap.SelectInt("SELECT COUNT(*) FROM people")
|
|
||||||
c.Assert(err, IsNil)
|
|
||||||
c.Assert(id, Equals, int64(0))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *SqliteMigrateSuite) TestMigrateDown(c *C) {
|
|
||||||
migrations := &FileMigrationSource{
|
|
||||||
Dir: "test-migrations",
|
|
||||||
}
|
|
||||||
|
|
||||||
n, err := Exec(s.Db, "sqlite3", migrations, Up)
|
|
||||||
c.Assert(err, IsNil)
|
|
||||||
c.Assert(n, Equals, 2)
|
|
||||||
|
|
||||||
// Has data
|
|
||||||
id, err := s.DbMap.SelectInt("SELECT id FROM people")
|
|
||||||
c.Assert(err, IsNil)
|
|
||||||
c.Assert(id, Equals, int64(1))
|
|
||||||
|
|
||||||
// Undo the last one
|
|
||||||
n, err = ExecMax(s.Db, "sqlite3", migrations, Down, 1)
|
|
||||||
c.Assert(err, IsNil)
|
|
||||||
c.Assert(n, Equals, 1)
|
|
||||||
|
|
||||||
// No more data
|
|
||||||
id, err = s.DbMap.SelectInt("SELECT COUNT(*) FROM people")
|
|
||||||
c.Assert(err, IsNil)
|
|
||||||
c.Assert(id, Equals, int64(0))
|
|
||||||
|
|
||||||
// Remove the table.
|
|
||||||
n, err = ExecMax(s.Db, "sqlite3", migrations, Down, 1)
|
|
||||||
c.Assert(err, IsNil)
|
|
||||||
c.Assert(n, Equals, 1)
|
|
||||||
|
|
||||||
// Cannot query it anymore
|
|
||||||
_, err = s.DbMap.SelectInt("SELECT COUNT(*) FROM people")
|
|
||||||
c.Assert(err, Not(IsNil))
|
|
||||||
|
|
||||||
// Nothing left to do.
|
|
||||||
n, err = ExecMax(s.Db, "sqlite3", migrations, Down, 1)
|
|
||||||
c.Assert(err, IsNil)
|
|
||||||
c.Assert(n, Equals, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *SqliteMigrateSuite) TestMigrateDownFull(c *C) {
|
|
||||||
migrations := &FileMigrationSource{
|
|
||||||
Dir: "test-migrations",
|
|
||||||
}
|
|
||||||
|
|
||||||
n, err := Exec(s.Db, "sqlite3", migrations, Up)
|
|
||||||
c.Assert(err, IsNil)
|
|
||||||
c.Assert(n, Equals, 2)
|
|
||||||
|
|
||||||
// Has data
|
|
||||||
id, err := s.DbMap.SelectInt("SELECT id FROM people")
|
|
||||||
c.Assert(err, IsNil)
|
|
||||||
c.Assert(id, Equals, int64(1))
|
|
||||||
|
|
||||||
// Undo the last one
|
|
||||||
n, err = Exec(s.Db, "sqlite3", migrations, Down)
|
|
||||||
c.Assert(err, IsNil)
|
|
||||||
c.Assert(n, Equals, 2)
|
|
||||||
|
|
||||||
// Cannot query it anymore
|
|
||||||
_, err = s.DbMap.SelectInt("SELECT COUNT(*) FROM people")
|
|
||||||
c.Assert(err, Not(IsNil))
|
|
||||||
|
|
||||||
// Nothing left to do.
|
|
||||||
n, err = Exec(s.Db, "sqlite3", migrations, Down)
|
|
||||||
c.Assert(err, IsNil)
|
|
||||||
c.Assert(n, Equals, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *SqliteMigrateSuite) TestMigrateTransaction(c *C) {
|
|
||||||
migrations := &MemoryMigrationSource{
|
|
||||||
Migrations: []*Migration{
|
|
||||||
sqliteMigrations[0],
|
|
||||||
sqliteMigrations[1],
|
|
||||||
&Migration{
|
|
||||||
Id: "125",
|
|
||||||
Up: []string{"INSERT INTO people (id, first_name) VALUES (1, 'Test')", "SELECT fail"},
|
|
||||||
Down: []string{}, // Not important here
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
// Should fail, transaction should roll back the INSERT.
|
|
||||||
n, err := Exec(s.Db, "sqlite3", migrations, Up)
|
|
||||||
c.Assert(err, Not(IsNil))
|
|
||||||
c.Assert(n, Equals, 2)
|
|
||||||
|
|
||||||
// INSERT should be rolled back
|
|
||||||
count, err := s.DbMap.SelectInt("SELECT COUNT(*) FROM people")
|
|
||||||
c.Assert(err, IsNil)
|
|
||||||
c.Assert(count, Equals, int64(0))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *SqliteMigrateSuite) TestPlanMigration(c *C) {
|
|
||||||
migrations := &MemoryMigrationSource{
|
|
||||||
Migrations: []*Migration{
|
|
||||||
&Migration{
|
|
||||||
Id: "1_create_table.sql",
|
|
||||||
Up: []string{"CREATE TABLE people (id int)"},
|
|
||||||
Down: []string{"DROP TABLE people"},
|
|
||||||
},
|
|
||||||
&Migration{
|
|
||||||
Id: "2_alter_table.sql",
|
|
||||||
Up: []string{"ALTER TABLE people ADD COLUMN first_name text"},
|
|
||||||
Down: []string{"SELECT 0"}, // Not really supported
|
|
||||||
},
|
|
||||||
&Migration{
|
|
||||||
Id: "10_add_last_name.sql",
|
|
||||||
Up: []string{"ALTER TABLE people ADD COLUMN last_name text"},
|
|
||||||
Down: []string{"ALTER TABLE people DROP COLUMN last_name"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
n, err := Exec(s.Db, "sqlite3", migrations, Up)
|
|
||||||
c.Assert(err, IsNil)
|
|
||||||
c.Assert(n, Equals, 3)
|
|
||||||
|
|
||||||
migrations.Migrations = append(migrations.Migrations, &Migration{
|
|
||||||
Id: "11_add_middle_name.sql",
|
|
||||||
Up: []string{"ALTER TABLE people ADD COLUMN middle_name text"},
|
|
||||||
Down: []string{"ALTER TABLE people DROP COLUMN middle_name"},
|
|
||||||
})
|
|
||||||
|
|
||||||
plannedMigrations, _, err := PlanMigration(s.Db, "sqlite3", migrations, Up, 0)
|
|
||||||
c.Assert(err, IsNil)
|
|
||||||
c.Assert(plannedMigrations, HasLen, 1)
|
|
||||||
c.Assert(plannedMigrations[0].Migration, Equals, migrations.Migrations[3])
|
|
||||||
|
|
||||||
plannedMigrations, _, err = PlanMigration(s.Db, "sqlite3", migrations, Down, 0)
|
|
||||||
c.Assert(err, IsNil)
|
|
||||||
c.Assert(plannedMigrations, HasLen, 3)
|
|
||||||
c.Assert(plannedMigrations[0].Migration, Equals, migrations.Migrations[2])
|
|
||||||
c.Assert(plannedMigrations[1].Migration, Equals, migrations.Migrations[1])
|
|
||||||
c.Assert(plannedMigrations[2].Migration, Equals, migrations.Migrations[0])
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *SqliteMigrateSuite) TestPlanMigrationWithHoles(c *C) {
|
|
||||||
up := "SELECT 0"
|
|
||||||
down := "SELECT 1"
|
|
||||||
migrations := &MemoryMigrationSource{
|
|
||||||
Migrations: []*Migration{
|
|
||||||
&Migration{
|
|
||||||
Id: "1",
|
|
||||||
Up: []string{up},
|
|
||||||
Down: []string{down},
|
|
||||||
},
|
|
||||||
&Migration{
|
|
||||||
Id: "3",
|
|
||||||
Up: []string{up},
|
|
||||||
Down: []string{down},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
n, err := Exec(s.Db, "sqlite3", migrations, Up)
|
|
||||||
c.Assert(err, IsNil)
|
|
||||||
c.Assert(n, Equals, 2)
|
|
||||||
|
|
||||||
migrations.Migrations = append(migrations.Migrations, &Migration{
|
|
||||||
Id: "2",
|
|
||||||
Up: []string{up},
|
|
||||||
Down: []string{down},
|
|
||||||
})
|
|
||||||
|
|
||||||
migrations.Migrations = append(migrations.Migrations, &Migration{
|
|
||||||
Id: "4",
|
|
||||||
Up: []string{up},
|
|
||||||
Down: []string{down},
|
|
||||||
})
|
|
||||||
|
|
||||||
migrations.Migrations = append(migrations.Migrations, &Migration{
|
|
||||||
Id: "5",
|
|
||||||
Up: []string{up},
|
|
||||||
Down: []string{down},
|
|
||||||
})
|
|
||||||
|
|
||||||
// apply all the missing migrations
|
|
||||||
plannedMigrations, _, err := PlanMigration(s.Db, "sqlite3", migrations, Up, 0)
|
|
||||||
c.Assert(err, IsNil)
|
|
||||||
c.Assert(plannedMigrations, HasLen, 3)
|
|
||||||
c.Assert(plannedMigrations[0].Migration.Id, Equals, "2")
|
|
||||||
c.Assert(plannedMigrations[0].Queries[0], Equals, up)
|
|
||||||
c.Assert(plannedMigrations[1].Migration.Id, Equals, "4")
|
|
||||||
c.Assert(plannedMigrations[1].Queries[0], Equals, up)
|
|
||||||
c.Assert(plannedMigrations[2].Migration.Id, Equals, "5")
|
|
||||||
c.Assert(plannedMigrations[2].Queries[0], Equals, up)
|
|
||||||
|
|
||||||
// first catch up to current target state 123, then migrate down 1 step to 12
|
|
||||||
plannedMigrations, _, err = PlanMigration(s.Db, "sqlite3", migrations, Down, 1)
|
|
||||||
c.Assert(err, IsNil)
|
|
||||||
c.Assert(plannedMigrations, HasLen, 2)
|
|
||||||
c.Assert(plannedMigrations[0].Migration.Id, Equals, "2")
|
|
||||||
c.Assert(plannedMigrations[0].Queries[0], Equals, up)
|
|
||||||
c.Assert(plannedMigrations[1].Migration.Id, Equals, "3")
|
|
||||||
c.Assert(plannedMigrations[1].Queries[0], Equals, down)
|
|
||||||
|
|
||||||
// first catch up to current target state 123, then migrate down 2 steps to 1
|
|
||||||
plannedMigrations, _, err = PlanMigration(s.Db, "sqlite3", migrations, Down, 2)
|
|
||||||
c.Assert(err, IsNil)
|
|
||||||
c.Assert(plannedMigrations, HasLen, 3)
|
|
||||||
c.Assert(plannedMigrations[0].Migration.Id, Equals, "2")
|
|
||||||
c.Assert(plannedMigrations[0].Queries[0], Equals, up)
|
|
||||||
c.Assert(plannedMigrations[1].Migration.Id, Equals, "3")
|
|
||||||
c.Assert(plannedMigrations[1].Queries[0], Equals, down)
|
|
||||||
c.Assert(plannedMigrations[2].Migration.Id, Equals, "2")
|
|
||||||
c.Assert(plannedMigrations[2].Queries[0], Equals, down)
|
|
||||||
}
|
|
34
Godeps/_workspace/src/github.com/rubenv/sql-migrate/sort_test.go
generated
vendored
34
Godeps/_workspace/src/github.com/rubenv/sql-migrate/sort_test.go
generated
vendored
|
@ -1,34 +0,0 @@
|
||||||
package migrate
|
|
||||||
|
|
||||||
import (
|
|
||||||
"sort"
|
|
||||||
. "gopkg.in/check.v1"
|
|
||||||
)
|
|
||||||
|
|
||||||
type SortSuite struct{}
|
|
||||||
|
|
||||||
var _ = Suite(&SortSuite{})
|
|
||||||
|
|
||||||
func (s *SortSuite) TestSortMigrations(c *C) {
|
|
||||||
var migrations = byId([]*Migration{
|
|
||||||
&Migration{Id: "10_abc", Up: nil, Down: nil},
|
|
||||||
&Migration{Id: "120_cde", Up: nil, Down: nil},
|
|
||||||
&Migration{Id: "1_abc", Up: nil, Down: nil},
|
|
||||||
&Migration{Id: "efg", Up: nil, Down: nil},
|
|
||||||
&Migration{Id: "2_cde", Up: nil, Down: nil},
|
|
||||||
&Migration{Id: "35_cde", Up: nil, Down: nil},
|
|
||||||
&Migration{Id: "3_efg", Up: nil, Down: nil},
|
|
||||||
&Migration{Id: "4_abc", Up: nil, Down: nil},
|
|
||||||
})
|
|
||||||
|
|
||||||
sort.Sort(migrations)
|
|
||||||
c.Assert(migrations, HasLen, 8)
|
|
||||||
c.Assert(migrations[0].Id, Equals, "1_abc")
|
|
||||||
c.Assert(migrations[1].Id, Equals, "2_cde")
|
|
||||||
c.Assert(migrations[2].Id, Equals, "3_efg")
|
|
||||||
c.Assert(migrations[3].Id, Equals, "4_abc")
|
|
||||||
c.Assert(migrations[4].Id, Equals, "10_abc")
|
|
||||||
c.Assert(migrations[5].Id, Equals, "35_cde")
|
|
||||||
c.Assert(migrations[6].Id, Equals, "120_cde")
|
|
||||||
c.Assert(migrations[7].Id, Equals, "efg")
|
|
||||||
}
|
|
1
Godeps/_workspace/src/github.com/rubenv/sql-migrate/sql-migrate/main_test.go
generated
vendored
1
Godeps/_workspace/src/github.com/rubenv/sql-migrate/sql-migrate/main_test.go
generated
vendored
|
@ -1 +0,0 @@
|
||||||
package main
|
|
151
Godeps/_workspace/src/github.com/rubenv/sql-migrate/sqlparse/sqlparse_test.go
generated
vendored
151
Godeps/_workspace/src/github.com/rubenv/sql-migrate/sqlparse/sqlparse_test.go
generated
vendored
|
@ -1,151 +0,0 @@
|
||||||
package sqlparse
|
|
||||||
|
|
||||||
import (
|
|
||||||
"strings"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
. "gopkg.in/check.v1"
|
|
||||||
)
|
|
||||||
|
|
||||||
func Test(t *testing.T) { TestingT(t) }
|
|
||||||
|
|
||||||
type SqlParseSuite struct {
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ = Suite(&SqlParseSuite{})
|
|
||||||
|
|
||||||
func (s *SqlParseSuite) TestSemicolons(c *C) {
|
|
||||||
type testData struct {
|
|
||||||
line string
|
|
||||||
result bool
|
|
||||||
}
|
|
||||||
|
|
||||||
tests := []testData{
|
|
||||||
{
|
|
||||||
line: "END;",
|
|
||||||
result: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
line: "END; -- comment",
|
|
||||||
result: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
line: "END ; -- comment",
|
|
||||||
result: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
line: "END -- comment",
|
|
||||||
result: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
line: "END -- comment ;",
|
|
||||||
result: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
line: "END \" ; \" -- comment",
|
|
||||||
result: false,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, test := range tests {
|
|
||||||
r := endsWithSemicolon(test.line)
|
|
||||||
c.Assert(r, Equals, test.result)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *SqlParseSuite) TestSplitStatements(c *C) {
|
|
||||||
type testData struct {
|
|
||||||
sql string
|
|
||||||
direction bool
|
|
||||||
count int
|
|
||||||
}
|
|
||||||
|
|
||||||
tests := []testData{
|
|
||||||
{
|
|
||||||
sql: functxt,
|
|
||||||
direction: true,
|
|
||||||
count: 2,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
sql: functxt,
|
|
||||||
direction: false,
|
|
||||||
count: 2,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
sql: multitxt,
|
|
||||||
direction: true,
|
|
||||||
count: 2,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
sql: multitxt,
|
|
||||||
direction: false,
|
|
||||||
count: 2,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, test := range tests {
|
|
||||||
stmts, err := SplitSQLStatements(strings.NewReader(test.sql), test.direction)
|
|
||||||
c.Assert(err, IsNil)
|
|
||||||
c.Assert(stmts, HasLen, test.count)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var functxt = `-- +migrate Up
|
|
||||||
CREATE TABLE IF NOT EXISTS histories (
|
|
||||||
id BIGSERIAL PRIMARY KEY,
|
|
||||||
current_value varchar(2000) NOT NULL,
|
|
||||||
created_at timestamp with time zone NOT NULL
|
|
||||||
);
|
|
||||||
|
|
||||||
-- +migrate StatementBegin
|
|
||||||
CREATE OR REPLACE FUNCTION histories_partition_creation( DATE, DATE )
|
|
||||||
returns void AS $$
|
|
||||||
DECLARE
|
|
||||||
create_query text;
|
|
||||||
BEGIN
|
|
||||||
FOR create_query IN SELECT
|
|
||||||
'CREATE TABLE IF NOT EXISTS histories_'
|
|
||||||
|| TO_CHAR( d, 'YYYY_MM' )
|
|
||||||
|| ' ( CHECK( created_at >= timestamp '''
|
|
||||||
|| TO_CHAR( d, 'YYYY-MM-DD 00:00:00' )
|
|
||||||
|| ''' AND created_at < timestamp '''
|
|
||||||
|| TO_CHAR( d + INTERVAL '1 month', 'YYYY-MM-DD 00:00:00' )
|
|
||||||
|| ''' ) ) inherits ( histories );'
|
|
||||||
FROM generate_series( $1, $2, '1 month' ) AS d
|
|
||||||
LOOP
|
|
||||||
EXECUTE create_query;
|
|
||||||
END LOOP; -- LOOP END
|
|
||||||
END; -- FUNCTION END
|
|
||||||
$$
|
|
||||||
language plpgsql;
|
|
||||||
-- +migrate StatementEnd
|
|
||||||
|
|
||||||
-- +migrate Down
|
|
||||||
drop function histories_partition_creation(DATE, DATE);
|
|
||||||
drop TABLE histories;
|
|
||||||
`
|
|
||||||
|
|
||||||
// test multiple up/down transitions in a single script
|
|
||||||
var multitxt = `-- +migrate Up
|
|
||||||
CREATE TABLE post (
|
|
||||||
id int NOT NULL,
|
|
||||||
title text,
|
|
||||||
body text,
|
|
||||||
PRIMARY KEY(id)
|
|
||||||
);
|
|
||||||
|
|
||||||
-- +migrate Down
|
|
||||||
DROP TABLE post;
|
|
||||||
|
|
||||||
-- +migrate Up
|
|
||||||
CREATE TABLE fancier_post (
|
|
||||||
id int NOT NULL,
|
|
||||||
title text,
|
|
||||||
body text,
|
|
||||||
created_on timestamp without time zone,
|
|
||||||
PRIMARY KEY(id)
|
|
||||||
);
|
|
||||||
|
|
||||||
-- +migrate Down
|
|
||||||
DROP TABLE fancier_post;
|
|
||||||
`
|
|
101
Godeps/_workspace/src/github.com/rubenv/sql-migrate/toapply_test.go
generated
vendored
101
Godeps/_workspace/src/github.com/rubenv/sql-migrate/toapply_test.go
generated
vendored
|
@ -1,101 +0,0 @@
|
||||||
package migrate
|
|
||||||
|
|
||||||
import (
|
|
||||||
"sort"
|
|
||||||
. "gopkg.in/check.v1"
|
|
||||||
)
|
|
||||||
|
|
||||||
var toapplyMigrations = []*Migration{
|
|
||||||
&Migration{Id: "abc", Up: nil, Down: nil},
|
|
||||||
&Migration{Id: "cde", Up: nil, Down: nil},
|
|
||||||
&Migration{Id: "efg", Up: nil, Down: nil},
|
|
||||||
}
|
|
||||||
|
|
||||||
type ToApplyMigrateSuite struct {
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ = Suite(&ToApplyMigrateSuite{})
|
|
||||||
|
|
||||||
func (s *ToApplyMigrateSuite) TestGetAll(c *C) {
|
|
||||||
toApply := ToApply(toapplyMigrations, "", Up)
|
|
||||||
c.Assert(toApply, HasLen, 3)
|
|
||||||
c.Assert(toApply[0], Equals, toapplyMigrations[0])
|
|
||||||
c.Assert(toApply[1], Equals, toapplyMigrations[1])
|
|
||||||
c.Assert(toApply[2], Equals, toapplyMigrations[2])
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *ToApplyMigrateSuite) TestGetAbc(c *C) {
|
|
||||||
toApply := ToApply(toapplyMigrations, "abc", Up)
|
|
||||||
c.Assert(toApply, HasLen, 2)
|
|
||||||
c.Assert(toApply[0], Equals, toapplyMigrations[1])
|
|
||||||
c.Assert(toApply[1], Equals, toapplyMigrations[2])
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *ToApplyMigrateSuite) TestGetCde(c *C) {
|
|
||||||
toApply := ToApply(toapplyMigrations, "cde", Up)
|
|
||||||
c.Assert(toApply, HasLen, 1)
|
|
||||||
c.Assert(toApply[0], Equals, toapplyMigrations[2])
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *ToApplyMigrateSuite) TestGetDone(c *C) {
|
|
||||||
toApply := ToApply(toapplyMigrations, "efg", Up)
|
|
||||||
c.Assert(toApply, HasLen, 0)
|
|
||||||
|
|
||||||
toApply = ToApply(toapplyMigrations, "zzz", Up)
|
|
||||||
c.Assert(toApply, HasLen, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *ToApplyMigrateSuite) TestDownDone(c *C) {
|
|
||||||
toApply := ToApply(toapplyMigrations, "", Down)
|
|
||||||
c.Assert(toApply, HasLen, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *ToApplyMigrateSuite) TestDownCde(c *C) {
|
|
||||||
toApply := ToApply(toapplyMigrations, "cde", Down)
|
|
||||||
c.Assert(toApply, HasLen, 2)
|
|
||||||
c.Assert(toApply[0], Equals, toapplyMigrations[1])
|
|
||||||
c.Assert(toApply[1], Equals, toapplyMigrations[0])
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *ToApplyMigrateSuite) TestDownAbc(c *C) {
|
|
||||||
toApply := ToApply(toapplyMigrations, "abc", Down)
|
|
||||||
c.Assert(toApply, HasLen, 1)
|
|
||||||
c.Assert(toApply[0], Equals, toapplyMigrations[0])
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *ToApplyMigrateSuite) TestDownAll(c *C) {
|
|
||||||
toApply := ToApply(toapplyMigrations, "efg", Down)
|
|
||||||
c.Assert(toApply, HasLen, 3)
|
|
||||||
c.Assert(toApply[0], Equals, toapplyMigrations[2])
|
|
||||||
c.Assert(toApply[1], Equals, toapplyMigrations[1])
|
|
||||||
c.Assert(toApply[2], Equals, toapplyMigrations[0])
|
|
||||||
|
|
||||||
toApply = ToApply(toapplyMigrations, "zzz", Down)
|
|
||||||
c.Assert(toApply, HasLen, 3)
|
|
||||||
c.Assert(toApply[0], Equals, toapplyMigrations[2])
|
|
||||||
c.Assert(toApply[1], Equals, toapplyMigrations[1])
|
|
||||||
c.Assert(toApply[2], Equals, toapplyMigrations[0])
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *ToApplyMigrateSuite) TestAlphaNumericMigrations(c *C) {
|
|
||||||
var migrations = byId([]*Migration{
|
|
||||||
&Migration{Id: "10_abc", Up: nil, Down: nil},
|
|
||||||
&Migration{Id: "1_abc", Up: nil, Down: nil},
|
|
||||||
&Migration{Id: "efg", Up: nil, Down: nil},
|
|
||||||
&Migration{Id: "2_cde", Up: nil, Down: nil},
|
|
||||||
&Migration{Id: "35_cde", Up: nil, Down: nil},
|
|
||||||
})
|
|
||||||
|
|
||||||
sort.Sort(migrations)
|
|
||||||
|
|
||||||
toApplyUp := ToApply(migrations, "2_cde", Up)
|
|
||||||
c.Assert(toApplyUp, HasLen, 3)
|
|
||||||
c.Assert(toApplyUp[0].Id, Equals, "10_abc")
|
|
||||||
c.Assert(toApplyUp[1].Id, Equals, "35_cde")
|
|
||||||
c.Assert(toApplyUp[2].Id, Equals, "efg")
|
|
||||||
|
|
||||||
toApplyDown := ToApply(migrations, "2_cde", Down)
|
|
||||||
c.Assert(toApplyDown, HasLen, 2)
|
|
||||||
c.Assert(toApplyDown[0].Id, Equals, "2_cde")
|
|
||||||
c.Assert(toApplyDown[1].Id, Equals, "1_abc")
|
|
||||||
}
|
|
226
Godeps/_workspace/src/golang.org/x/crypto/bcrypt/bcrypt_test.go
generated
vendored
226
Godeps/_workspace/src/golang.org/x/crypto/bcrypt/bcrypt_test.go
generated
vendored
|
@ -1,226 +0,0 @@
|
||||||
// Copyright 2011 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.
|
|
||||||
|
|
||||||
package bcrypt
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"fmt"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestBcryptingIsEasy(t *testing.T) {
|
|
||||||
pass := []byte("mypassword")
|
|
||||||
hp, err := GenerateFromPassword(pass, 0)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("GenerateFromPassword error: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if CompareHashAndPassword(hp, pass) != nil {
|
|
||||||
t.Errorf("%v should hash %s correctly", hp, pass)
|
|
||||||
}
|
|
||||||
|
|
||||||
notPass := "notthepass"
|
|
||||||
err = CompareHashAndPassword(hp, []byte(notPass))
|
|
||||||
if err != ErrMismatchedHashAndPassword {
|
|
||||||
t.Errorf("%v and %s should be mismatched", hp, notPass)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestBcryptingIsCorrect(t *testing.T) {
|
|
||||||
pass := []byte("allmine")
|
|
||||||
salt := []byte("XajjQvNhvvRt5GSeFk1xFe")
|
|
||||||
expectedHash := []byte("$2a$10$XajjQvNhvvRt5GSeFk1xFeyqRrsxkhBkUiQeg0dt.wU1qD4aFDcga")
|
|
||||||
|
|
||||||
hash, err := bcrypt(pass, 10, salt)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("bcrypt blew up: %v", err)
|
|
||||||
}
|
|
||||||
if !bytes.HasSuffix(expectedHash, hash) {
|
|
||||||
t.Errorf("%v should be the suffix of %v", hash, expectedHash)
|
|
||||||
}
|
|
||||||
|
|
||||||
h, err := newFromHash(expectedHash)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("Unable to parse %s: %v", string(expectedHash), err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// This is not the safe way to compare these hashes. We do this only for
|
|
||||||
// testing clarity. Use bcrypt.CompareHashAndPassword()
|
|
||||||
if err == nil && !bytes.Equal(expectedHash, h.Hash()) {
|
|
||||||
t.Errorf("Parsed hash %v should equal %v", h.Hash(), expectedHash)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestVeryShortPasswords(t *testing.T) {
|
|
||||||
key := []byte("k")
|
|
||||||
salt := []byte("XajjQvNhvvRt5GSeFk1xFe")
|
|
||||||
_, err := bcrypt(key, 10, salt)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("One byte key resulted in error: %s", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTooLongPasswordsWork(t *testing.T) {
|
|
||||||
salt := []byte("XajjQvNhvvRt5GSeFk1xFe")
|
|
||||||
// One byte over the usual 56 byte limit that blowfish has
|
|
||||||
tooLongPass := []byte("012345678901234567890123456789012345678901234567890123456")
|
|
||||||
tooLongExpected := []byte("$2a$10$XajjQvNhvvRt5GSeFk1xFe5l47dONXg781AmZtd869sO8zfsHuw7C")
|
|
||||||
hash, err := bcrypt(tooLongPass, 10, salt)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("bcrypt blew up on long password: %v", err)
|
|
||||||
}
|
|
||||||
if !bytes.HasSuffix(tooLongExpected, hash) {
|
|
||||||
t.Errorf("%v should be the suffix of %v", hash, tooLongExpected)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type InvalidHashTest struct {
|
|
||||||
err error
|
|
||||||
hash []byte
|
|
||||||
}
|
|
||||||
|
|
||||||
var invalidTests = []InvalidHashTest{
|
|
||||||
{ErrHashTooShort, []byte("$2a$10$fooo")},
|
|
||||||
{ErrHashTooShort, []byte("$2a")},
|
|
||||||
{HashVersionTooNewError('3'), []byte("$3a$10$sssssssssssssssssssssshhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh")},
|
|
||||||
{InvalidHashPrefixError('%'), []byte("%2a$10$sssssssssssssssssssssshhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh")},
|
|
||||||
{InvalidCostError(32), []byte("$2a$32$sssssssssssssssssssssshhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh")},
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestInvalidHashErrors(t *testing.T) {
|
|
||||||
check := func(name string, expected, err error) {
|
|
||||||
if err == nil {
|
|
||||||
t.Errorf("%s: Should have returned an error", name)
|
|
||||||
}
|
|
||||||
if err != nil && err != expected {
|
|
||||||
t.Errorf("%s gave err %v but should have given %v", name, err, expected)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for _, iht := range invalidTests {
|
|
||||||
_, err := newFromHash(iht.hash)
|
|
||||||
check("newFromHash", iht.err, err)
|
|
||||||
err = CompareHashAndPassword(iht.hash, []byte("anything"))
|
|
||||||
check("CompareHashAndPassword", iht.err, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestUnpaddedBase64Encoding(t *testing.T) {
|
|
||||||
original := []byte{101, 201, 101, 75, 19, 227, 199, 20, 239, 236, 133, 32, 30, 109, 243, 30}
|
|
||||||
encodedOriginal := []byte("XajjQvNhvvRt5GSeFk1xFe")
|
|
||||||
|
|
||||||
encoded := base64Encode(original)
|
|
||||||
|
|
||||||
if !bytes.Equal(encodedOriginal, encoded) {
|
|
||||||
t.Errorf("Encoded %v should have equaled %v", encoded, encodedOriginal)
|
|
||||||
}
|
|
||||||
|
|
||||||
decoded, err := base64Decode(encodedOriginal)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("base64Decode blew up: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !bytes.Equal(decoded, original) {
|
|
||||||
t.Errorf("Decoded %v should have equaled %v", decoded, original)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCost(t *testing.T) {
|
|
||||||
suffix := "XajjQvNhvvRt5GSeFk1xFe5l47dONXg781AmZtd869sO8zfsHuw7C"
|
|
||||||
for _, vers := range []string{"2a", "2"} {
|
|
||||||
for _, cost := range []int{4, 10} {
|
|
||||||
s := fmt.Sprintf("$%s$%02d$%s", vers, cost, suffix)
|
|
||||||
h := []byte(s)
|
|
||||||
actual, err := Cost(h)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("Cost, error: %s", err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if actual != cost {
|
|
||||||
t.Errorf("Cost, expected: %d, actual: %d", cost, actual)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_, err := Cost([]byte("$a$a$" + suffix))
|
|
||||||
if err == nil {
|
|
||||||
t.Errorf("Cost, malformed but no error returned")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCostValidationInHash(t *testing.T) {
|
|
||||||
if testing.Short() {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
pass := []byte("mypassword")
|
|
||||||
|
|
||||||
for c := 0; c < MinCost; c++ {
|
|
||||||
p, _ := newFromPassword(pass, c)
|
|
||||||
if p.cost != DefaultCost {
|
|
||||||
t.Errorf("newFromPassword should default costs below %d to %d, but was %d", MinCost, DefaultCost, p.cost)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
p, _ := newFromPassword(pass, 14)
|
|
||||||
if p.cost != 14 {
|
|
||||||
t.Errorf("newFromPassword should default cost to 14, but was %d", p.cost)
|
|
||||||
}
|
|
||||||
|
|
||||||
hp, _ := newFromHash(p.Hash())
|
|
||||||
if p.cost != hp.cost {
|
|
||||||
t.Errorf("newFromHash should maintain the cost at %d, but was %d", p.cost, hp.cost)
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err := newFromPassword(pass, 32)
|
|
||||||
if err == nil {
|
|
||||||
t.Fatalf("newFromPassword: should return a cost error")
|
|
||||||
}
|
|
||||||
if err != InvalidCostError(32) {
|
|
||||||
t.Errorf("newFromPassword: should return cost error, got %#v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCostReturnsWithLeadingZeroes(t *testing.T) {
|
|
||||||
hp, _ := newFromPassword([]byte("abcdefgh"), 7)
|
|
||||||
cost := hp.Hash()[4:7]
|
|
||||||
expected := []byte("07$")
|
|
||||||
|
|
||||||
if !bytes.Equal(expected, cost) {
|
|
||||||
t.Errorf("single digit costs in hash should have leading zeros: was %v instead of %v", cost, expected)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestMinorNotRequired(t *testing.T) {
|
|
||||||
noMinorHash := []byte("$2$10$XajjQvNhvvRt5GSeFk1xFeyqRrsxkhBkUiQeg0dt.wU1qD4aFDcga")
|
|
||||||
h, err := newFromHash(noMinorHash)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("No minor hash blew up: %s", err)
|
|
||||||
}
|
|
||||||
if h.minor != 0 {
|
|
||||||
t.Errorf("Should leave minor version at 0, but was %d", h.minor)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !bytes.Equal(noMinorHash, h.Hash()) {
|
|
||||||
t.Errorf("Should generate hash %v, but created %v", noMinorHash, h.Hash())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkEqual(b *testing.B) {
|
|
||||||
b.StopTimer()
|
|
||||||
passwd := []byte("somepasswordyoulike")
|
|
||||||
hash, _ := GenerateFromPassword(passwd, 10)
|
|
||||||
b.StartTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
CompareHashAndPassword(hash, passwd)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkGeneration(b *testing.B) {
|
|
||||||
b.StopTimer()
|
|
||||||
passwd := []byte("mylongpassword1234")
|
|
||||||
b.StartTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
GenerateFromPassword(passwd, 10)
|
|
||||||
}
|
|
||||||
}
|
|
274
Godeps/_workspace/src/golang.org/x/crypto/blowfish/blowfish_test.go
generated
vendored
274
Godeps/_workspace/src/golang.org/x/crypto/blowfish/blowfish_test.go
generated
vendored
|
@ -1,274 +0,0 @@
|
||||||
// Copyright 2010 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.
|
|
||||||
|
|
||||||
package blowfish
|
|
||||||
|
|
||||||
import "testing"
|
|
||||||
|
|
||||||
type CryptTest struct {
|
|
||||||
key []byte
|
|
||||||
in []byte
|
|
||||||
out []byte
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test vector values are from http://www.schneier.com/code/vectors.txt.
|
|
||||||
var encryptTests = []CryptTest{
|
|
||||||
{
|
|
||||||
[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
|
||||||
[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
|
||||||
[]byte{0x4E, 0xF9, 0x97, 0x45, 0x61, 0x98, 0xDD, 0x78}},
|
|
||||||
{
|
|
||||||
[]byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
|
|
||||||
[]byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
|
|
||||||
[]byte{0x51, 0x86, 0x6F, 0xD5, 0xB8, 0x5E, 0xCB, 0x8A}},
|
|
||||||
{
|
|
||||||
[]byte{0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
|
||||||
[]byte{0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01},
|
|
||||||
[]byte{0x7D, 0x85, 0x6F, 0x9A, 0x61, 0x30, 0x63, 0xF2}},
|
|
||||||
{
|
|
||||||
[]byte{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11},
|
|
||||||
[]byte{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11},
|
|
||||||
[]byte{0x24, 0x66, 0xDD, 0x87, 0x8B, 0x96, 0x3C, 0x9D}},
|
|
||||||
|
|
||||||
{
|
|
||||||
[]byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF},
|
|
||||||
[]byte{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11},
|
|
||||||
[]byte{0x61, 0xF9, 0xC3, 0x80, 0x22, 0x81, 0xB0, 0x96}},
|
|
||||||
{
|
|
||||||
[]byte{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11},
|
|
||||||
[]byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF},
|
|
||||||
[]byte{0x7D, 0x0C, 0xC6, 0x30, 0xAF, 0xDA, 0x1E, 0xC7}},
|
|
||||||
{
|
|
||||||
[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
|
||||||
[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
|
||||||
[]byte{0x4E, 0xF9, 0x97, 0x45, 0x61, 0x98, 0xDD, 0x78}},
|
|
||||||
{
|
|
||||||
[]byte{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10},
|
|
||||||
[]byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF},
|
|
||||||
[]byte{0x0A, 0xCE, 0xAB, 0x0F, 0xC6, 0xA0, 0xA2, 0x8D}},
|
|
||||||
{
|
|
||||||
[]byte{0x7C, 0xA1, 0x10, 0x45, 0x4A, 0x1A, 0x6E, 0x57},
|
|
||||||
[]byte{0x01, 0xA1, 0xD6, 0xD0, 0x39, 0x77, 0x67, 0x42},
|
|
||||||
[]byte{0x59, 0xC6, 0x82, 0x45, 0xEB, 0x05, 0x28, 0x2B}},
|
|
||||||
{
|
|
||||||
[]byte{0x01, 0x31, 0xD9, 0x61, 0x9D, 0xC1, 0x37, 0x6E},
|
|
||||||
[]byte{0x5C, 0xD5, 0x4C, 0xA8, 0x3D, 0xEF, 0x57, 0xDA},
|
|
||||||
[]byte{0xB1, 0xB8, 0xCC, 0x0B, 0x25, 0x0F, 0x09, 0xA0}},
|
|
||||||
{
|
|
||||||
[]byte{0x07, 0xA1, 0x13, 0x3E, 0x4A, 0x0B, 0x26, 0x86},
|
|
||||||
[]byte{0x02, 0x48, 0xD4, 0x38, 0x06, 0xF6, 0x71, 0x72},
|
|
||||||
[]byte{0x17, 0x30, 0xE5, 0x77, 0x8B, 0xEA, 0x1D, 0xA4}},
|
|
||||||
{
|
|
||||||
[]byte{0x38, 0x49, 0x67, 0x4C, 0x26, 0x02, 0x31, 0x9E},
|
|
||||||
[]byte{0x51, 0x45, 0x4B, 0x58, 0x2D, 0xDF, 0x44, 0x0A},
|
|
||||||
[]byte{0xA2, 0x5E, 0x78, 0x56, 0xCF, 0x26, 0x51, 0xEB}},
|
|
||||||
{
|
|
||||||
[]byte{0x04, 0xB9, 0x15, 0xBA, 0x43, 0xFE, 0xB5, 0xB6},
|
|
||||||
[]byte{0x42, 0xFD, 0x44, 0x30, 0x59, 0x57, 0x7F, 0xA2},
|
|
||||||
[]byte{0x35, 0x38, 0x82, 0xB1, 0x09, 0xCE, 0x8F, 0x1A}},
|
|
||||||
{
|
|
||||||
[]byte{0x01, 0x13, 0xB9, 0x70, 0xFD, 0x34, 0xF2, 0xCE},
|
|
||||||
[]byte{0x05, 0x9B, 0x5E, 0x08, 0x51, 0xCF, 0x14, 0x3A},
|
|
||||||
[]byte{0x48, 0xF4, 0xD0, 0x88, 0x4C, 0x37, 0x99, 0x18}},
|
|
||||||
{
|
|
||||||
[]byte{0x01, 0x70, 0xF1, 0x75, 0x46, 0x8F, 0xB5, 0xE6},
|
|
||||||
[]byte{0x07, 0x56, 0xD8, 0xE0, 0x77, 0x47, 0x61, 0xD2},
|
|
||||||
[]byte{0x43, 0x21, 0x93, 0xB7, 0x89, 0x51, 0xFC, 0x98}},
|
|
||||||
{
|
|
||||||
[]byte{0x43, 0x29, 0x7F, 0xAD, 0x38, 0xE3, 0x73, 0xFE},
|
|
||||||
[]byte{0x76, 0x25, 0x14, 0xB8, 0x29, 0xBF, 0x48, 0x6A},
|
|
||||||
[]byte{0x13, 0xF0, 0x41, 0x54, 0xD6, 0x9D, 0x1A, 0xE5}},
|
|
||||||
{
|
|
||||||
[]byte{0x07, 0xA7, 0x13, 0x70, 0x45, 0xDA, 0x2A, 0x16},
|
|
||||||
[]byte{0x3B, 0xDD, 0x11, 0x90, 0x49, 0x37, 0x28, 0x02},
|
|
||||||
[]byte{0x2E, 0xED, 0xDA, 0x93, 0xFF, 0xD3, 0x9C, 0x79}},
|
|
||||||
{
|
|
||||||
[]byte{0x04, 0x68, 0x91, 0x04, 0xC2, 0xFD, 0x3B, 0x2F},
|
|
||||||
[]byte{0x26, 0x95, 0x5F, 0x68, 0x35, 0xAF, 0x60, 0x9A},
|
|
||||||
[]byte{0xD8, 0x87, 0xE0, 0x39, 0x3C, 0x2D, 0xA6, 0xE3}},
|
|
||||||
{
|
|
||||||
[]byte{0x37, 0xD0, 0x6B, 0xB5, 0x16, 0xCB, 0x75, 0x46},
|
|
||||||
[]byte{0x16, 0x4D, 0x5E, 0x40, 0x4F, 0x27, 0x52, 0x32},
|
|
||||||
[]byte{0x5F, 0x99, 0xD0, 0x4F, 0x5B, 0x16, 0x39, 0x69}},
|
|
||||||
{
|
|
||||||
[]byte{0x1F, 0x08, 0x26, 0x0D, 0x1A, 0xC2, 0x46, 0x5E},
|
|
||||||
[]byte{0x6B, 0x05, 0x6E, 0x18, 0x75, 0x9F, 0x5C, 0xCA},
|
|
||||||
[]byte{0x4A, 0x05, 0x7A, 0x3B, 0x24, 0xD3, 0x97, 0x7B}},
|
|
||||||
{
|
|
||||||
[]byte{0x58, 0x40, 0x23, 0x64, 0x1A, 0xBA, 0x61, 0x76},
|
|
||||||
[]byte{0x00, 0x4B, 0xD6, 0xEF, 0x09, 0x17, 0x60, 0x62},
|
|
||||||
[]byte{0x45, 0x20, 0x31, 0xC1, 0xE4, 0xFA, 0xDA, 0x8E}},
|
|
||||||
{
|
|
||||||
[]byte{0x02, 0x58, 0x16, 0x16, 0x46, 0x29, 0xB0, 0x07},
|
|
||||||
[]byte{0x48, 0x0D, 0x39, 0x00, 0x6E, 0xE7, 0x62, 0xF2},
|
|
||||||
[]byte{0x75, 0x55, 0xAE, 0x39, 0xF5, 0x9B, 0x87, 0xBD}},
|
|
||||||
{
|
|
||||||
[]byte{0x49, 0x79, 0x3E, 0xBC, 0x79, 0xB3, 0x25, 0x8F},
|
|
||||||
[]byte{0x43, 0x75, 0x40, 0xC8, 0x69, 0x8F, 0x3C, 0xFA},
|
|
||||||
[]byte{0x53, 0xC5, 0x5F, 0x9C, 0xB4, 0x9F, 0xC0, 0x19}},
|
|
||||||
{
|
|
||||||
[]byte{0x4F, 0xB0, 0x5E, 0x15, 0x15, 0xAB, 0x73, 0xA7},
|
|
||||||
[]byte{0x07, 0x2D, 0x43, 0xA0, 0x77, 0x07, 0x52, 0x92},
|
|
||||||
[]byte{0x7A, 0x8E, 0x7B, 0xFA, 0x93, 0x7E, 0x89, 0xA3}},
|
|
||||||
{
|
|
||||||
[]byte{0x49, 0xE9, 0x5D, 0x6D, 0x4C, 0xA2, 0x29, 0xBF},
|
|
||||||
[]byte{0x02, 0xFE, 0x55, 0x77, 0x81, 0x17, 0xF1, 0x2A},
|
|
||||||
[]byte{0xCF, 0x9C, 0x5D, 0x7A, 0x49, 0x86, 0xAD, 0xB5}},
|
|
||||||
{
|
|
||||||
[]byte{0x01, 0x83, 0x10, 0xDC, 0x40, 0x9B, 0x26, 0xD6},
|
|
||||||
[]byte{0x1D, 0x9D, 0x5C, 0x50, 0x18, 0xF7, 0x28, 0xC2},
|
|
||||||
[]byte{0xD1, 0xAB, 0xB2, 0x90, 0x65, 0x8B, 0xC7, 0x78}},
|
|
||||||
{
|
|
||||||
[]byte{0x1C, 0x58, 0x7F, 0x1C, 0x13, 0x92, 0x4F, 0xEF},
|
|
||||||
[]byte{0x30, 0x55, 0x32, 0x28, 0x6D, 0x6F, 0x29, 0x5A},
|
|
||||||
[]byte{0x55, 0xCB, 0x37, 0x74, 0xD1, 0x3E, 0xF2, 0x01}},
|
|
||||||
{
|
|
||||||
[]byte{0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01},
|
|
||||||
[]byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF},
|
|
||||||
[]byte{0xFA, 0x34, 0xEC, 0x48, 0x47, 0xB2, 0x68, 0xB2}},
|
|
||||||
{
|
|
||||||
[]byte{0x1F, 0x1F, 0x1F, 0x1F, 0x0E, 0x0E, 0x0E, 0x0E},
|
|
||||||
[]byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF},
|
|
||||||
[]byte{0xA7, 0x90, 0x79, 0x51, 0x08, 0xEA, 0x3C, 0xAE}},
|
|
||||||
{
|
|
||||||
[]byte{0xE0, 0xFE, 0xE0, 0xFE, 0xF1, 0xFE, 0xF1, 0xFE},
|
|
||||||
[]byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF},
|
|
||||||
[]byte{0xC3, 0x9E, 0x07, 0x2D, 0x9F, 0xAC, 0x63, 0x1D}},
|
|
||||||
{
|
|
||||||
[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
|
||||||
[]byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
|
|
||||||
[]byte{0x01, 0x49, 0x33, 0xE0, 0xCD, 0xAF, 0xF6, 0xE4}},
|
|
||||||
{
|
|
||||||
[]byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
|
|
||||||
[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
|
||||||
[]byte{0xF2, 0x1E, 0x9A, 0x77, 0xB7, 0x1C, 0x49, 0xBC}},
|
|
||||||
{
|
|
||||||
[]byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF},
|
|
||||||
[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
|
||||||
[]byte{0x24, 0x59, 0x46, 0x88, 0x57, 0x54, 0x36, 0x9A}},
|
|
||||||
{
|
|
||||||
[]byte{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10},
|
|
||||||
[]byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
|
|
||||||
[]byte{0x6B, 0x5C, 0x5A, 0x9C, 0x5D, 0x9E, 0x0A, 0x5A}},
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCipherEncrypt(t *testing.T) {
|
|
||||||
for i, tt := range encryptTests {
|
|
||||||
c, err := NewCipher(tt.key)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("NewCipher(%d bytes) = %s", len(tt.key), err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
ct := make([]byte, len(tt.out))
|
|
||||||
c.Encrypt(ct, tt.in)
|
|
||||||
for j, v := range ct {
|
|
||||||
if v != tt.out[j] {
|
|
||||||
t.Errorf("Cipher.Encrypt, test vector #%d: cipher-text[%d] = %#x, expected %#x", i, j, v, tt.out[j])
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCipherDecrypt(t *testing.T) {
|
|
||||||
for i, tt := range encryptTests {
|
|
||||||
c, err := NewCipher(tt.key)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("NewCipher(%d bytes) = %s", len(tt.key), err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
pt := make([]byte, len(tt.in))
|
|
||||||
c.Decrypt(pt, tt.out)
|
|
||||||
for j, v := range pt {
|
|
||||||
if v != tt.in[j] {
|
|
||||||
t.Errorf("Cipher.Decrypt, test vector #%d: plain-text[%d] = %#x, expected %#x", i, j, v, tt.in[j])
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSaltedCipherKeyLength(t *testing.T) {
|
|
||||||
if _, err := NewSaltedCipher(nil, []byte{'a'}); err != KeySizeError(0) {
|
|
||||||
t.Errorf("NewSaltedCipher with short key, gave error %#v, expected %#v", err, KeySizeError(0))
|
|
||||||
}
|
|
||||||
|
|
||||||
// A 57-byte key. One over the typical blowfish restriction.
|
|
||||||
key := []byte("012345678901234567890123456789012345678901234567890123456")
|
|
||||||
if _, err := NewSaltedCipher(key, []byte{'a'}); err != nil {
|
|
||||||
t.Errorf("NewSaltedCipher with long key, gave error %#v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test vectors generated with Blowfish from OpenSSH.
|
|
||||||
var saltedVectors = [][8]byte{
|
|
||||||
{0x0c, 0x82, 0x3b, 0x7b, 0x8d, 0x01, 0x4b, 0x7e},
|
|
||||||
{0xd1, 0xe1, 0x93, 0xf0, 0x70, 0xa6, 0xdb, 0x12},
|
|
||||||
{0xfc, 0x5e, 0xba, 0xde, 0xcb, 0xf8, 0x59, 0xad},
|
|
||||||
{0x8a, 0x0c, 0x76, 0xe7, 0xdd, 0x2c, 0xd3, 0xa8},
|
|
||||||
{0x2c, 0xcb, 0x7b, 0xee, 0xac, 0x7b, 0x7f, 0xf8},
|
|
||||||
{0xbb, 0xf6, 0x30, 0x6f, 0xe1, 0x5d, 0x62, 0xbf},
|
|
||||||
{0x97, 0x1e, 0xc1, 0x3d, 0x3d, 0xe0, 0x11, 0xe9},
|
|
||||||
{0x06, 0xd7, 0x4d, 0xb1, 0x80, 0xa3, 0xb1, 0x38},
|
|
||||||
{0x67, 0xa1, 0xa9, 0x75, 0x0e, 0x5b, 0xc6, 0xb4},
|
|
||||||
{0x51, 0x0f, 0x33, 0x0e, 0x4f, 0x67, 0xd2, 0x0c},
|
|
||||||
{0xf1, 0x73, 0x7e, 0xd8, 0x44, 0xea, 0xdb, 0xe5},
|
|
||||||
{0x14, 0x0e, 0x16, 0xce, 0x7f, 0x4a, 0x9c, 0x7b},
|
|
||||||
{0x4b, 0xfe, 0x43, 0xfd, 0xbf, 0x36, 0x04, 0x47},
|
|
||||||
{0xb1, 0xeb, 0x3e, 0x15, 0x36, 0xa7, 0xbb, 0xe2},
|
|
||||||
{0x6d, 0x0b, 0x41, 0xdd, 0x00, 0x98, 0x0b, 0x19},
|
|
||||||
{0xd3, 0xce, 0x45, 0xce, 0x1d, 0x56, 0xb7, 0xfc},
|
|
||||||
{0xd9, 0xf0, 0xfd, 0xda, 0xc0, 0x23, 0xb7, 0x93},
|
|
||||||
{0x4c, 0x6f, 0xa1, 0xe4, 0x0c, 0xa8, 0xca, 0x57},
|
|
||||||
{0xe6, 0x2f, 0x28, 0xa7, 0x0c, 0x94, 0x0d, 0x08},
|
|
||||||
{0x8f, 0xe3, 0xf0, 0xb6, 0x29, 0xe3, 0x44, 0x03},
|
|
||||||
{0xff, 0x98, 0xdd, 0x04, 0x45, 0xb4, 0x6d, 0x1f},
|
|
||||||
{0x9e, 0x45, 0x4d, 0x18, 0x40, 0x53, 0xdb, 0xef},
|
|
||||||
{0xb7, 0x3b, 0xef, 0x29, 0xbe, 0xa8, 0x13, 0x71},
|
|
||||||
{0x02, 0x54, 0x55, 0x41, 0x8e, 0x04, 0xfc, 0xad},
|
|
||||||
{0x6a, 0x0a, 0xee, 0x7c, 0x10, 0xd9, 0x19, 0xfe},
|
|
||||||
{0x0a, 0x22, 0xd9, 0x41, 0xcc, 0x23, 0x87, 0x13},
|
|
||||||
{0x6e, 0xff, 0x1f, 0xff, 0x36, 0x17, 0x9c, 0xbe},
|
|
||||||
{0x79, 0xad, 0xb7, 0x40, 0xf4, 0x9f, 0x51, 0xa6},
|
|
||||||
{0x97, 0x81, 0x99, 0xa4, 0xde, 0x9e, 0x9f, 0xb6},
|
|
||||||
{0x12, 0x19, 0x7a, 0x28, 0xd0, 0xdc, 0xcc, 0x92},
|
|
||||||
{0x81, 0xda, 0x60, 0x1e, 0x0e, 0xdd, 0x65, 0x56},
|
|
||||||
{0x7d, 0x76, 0x20, 0xb2, 0x73, 0xc9, 0x9e, 0xee},
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSaltedCipher(t *testing.T) {
|
|
||||||
var key, salt [32]byte
|
|
||||||
for i := range key {
|
|
||||||
key[i] = byte(i)
|
|
||||||
salt[i] = byte(i + 32)
|
|
||||||
}
|
|
||||||
for i, v := range saltedVectors {
|
|
||||||
c, err := NewSaltedCipher(key[:], salt[:i])
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
var buf [8]byte
|
|
||||||
c.Encrypt(buf[:], buf[:])
|
|
||||||
if v != buf {
|
|
||||||
t.Errorf("%d: expected %x, got %x", i, v, buf)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkExpandKeyWithSalt(b *testing.B) {
|
|
||||||
key := make([]byte, 32)
|
|
||||||
salt := make([]byte, 16)
|
|
||||||
c, _ := NewCipher(key)
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
expandKeyWithSalt(key, salt, c)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkExpandKey(b *testing.B) {
|
|
||||||
key := make([]byte, 32)
|
|
||||||
c, _ := NewCipher(key)
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
ExpandKey(key, c)
|
|
||||||
}
|
|
||||||
}
|
|
109
Godeps/_workspace/src/golang.org/x/net/html/atom/atom_test.go
generated
vendored
109
Godeps/_workspace/src/golang.org/x/net/html/atom/atom_test.go
generated
vendored
|
@ -1,109 +0,0 @@
|
||||||
// Copyright 2012 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.
|
|
||||||
|
|
||||||
package atom
|
|
||||||
|
|
||||||
import (
|
|
||||||
"sort"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestKnown(t *testing.T) {
|
|
||||||
for _, s := range testAtomList {
|
|
||||||
if atom := Lookup([]byte(s)); atom.String() != s {
|
|
||||||
t.Errorf("Lookup(%q) = %#x (%q)", s, uint32(atom), atom.String())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestHits(t *testing.T) {
|
|
||||||
for _, a := range table {
|
|
||||||
if a == 0 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
got := Lookup([]byte(a.String()))
|
|
||||||
if got != a {
|
|
||||||
t.Errorf("Lookup(%q) = %#x, want %#x", a.String(), uint32(got), uint32(a))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestMisses(t *testing.T) {
|
|
||||||
testCases := []string{
|
|
||||||
"",
|
|
||||||
"\x00",
|
|
||||||
"\xff",
|
|
||||||
"A",
|
|
||||||
"DIV",
|
|
||||||
"Div",
|
|
||||||
"dIV",
|
|
||||||
"aa",
|
|
||||||
"a\x00",
|
|
||||||
"ab",
|
|
||||||
"abb",
|
|
||||||
"abbr0",
|
|
||||||
"abbr ",
|
|
||||||
" abbr",
|
|
||||||
" a",
|
|
||||||
"acceptcharset",
|
|
||||||
"acceptCharset",
|
|
||||||
"accept_charset",
|
|
||||||
"h0",
|
|
||||||
"h1h2",
|
|
||||||
"h7",
|
|
||||||
"onClick",
|
|
||||||
"λ",
|
|
||||||
// The following string has the same hash (0xa1d7fab7) as "onmouseover".
|
|
||||||
"\x00\x00\x00\x00\x00\x50\x18\xae\x38\xd0\xb7",
|
|
||||||
}
|
|
||||||
for _, tc := range testCases {
|
|
||||||
got := Lookup([]byte(tc))
|
|
||||||
if got != 0 {
|
|
||||||
t.Errorf("Lookup(%q): got %d, want 0", tc, got)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestForeignObject(t *testing.T) {
|
|
||||||
const (
|
|
||||||
afo = Foreignobject
|
|
||||||
afO = ForeignObject
|
|
||||||
sfo = "foreignobject"
|
|
||||||
sfO = "foreignObject"
|
|
||||||
)
|
|
||||||
if got := Lookup([]byte(sfo)); got != afo {
|
|
||||||
t.Errorf("Lookup(%q): got %#v, want %#v", sfo, got, afo)
|
|
||||||
}
|
|
||||||
if got := Lookup([]byte(sfO)); got != afO {
|
|
||||||
t.Errorf("Lookup(%q): got %#v, want %#v", sfO, got, afO)
|
|
||||||
}
|
|
||||||
if got := afo.String(); got != sfo {
|
|
||||||
t.Errorf("Atom(%#v).String(): got %q, want %q", afo, got, sfo)
|
|
||||||
}
|
|
||||||
if got := afO.String(); got != sfO {
|
|
||||||
t.Errorf("Atom(%#v).String(): got %q, want %q", afO, got, sfO)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkLookup(b *testing.B) {
|
|
||||||
sortedTable := make([]string, 0, len(table))
|
|
||||||
for _, a := range table {
|
|
||||||
if a != 0 {
|
|
||||||
sortedTable = append(sortedTable, a.String())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sort.Strings(sortedTable)
|
|
||||||
|
|
||||||
x := make([][]byte, 1000)
|
|
||||||
for i := range x {
|
|
||||||
x[i] = []byte(sortedTable[i%len(sortedTable)])
|
|
||||||
}
|
|
||||||
|
|
||||||
b.ResetTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
for _, s := range x {
|
|
||||||
Lookup(s)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
351
Godeps/_workspace/src/golang.org/x/net/html/atom/table_test.go
generated
vendored
351
Godeps/_workspace/src/golang.org/x/net/html/atom/table_test.go
generated
vendored
|
@ -1,351 +0,0 @@
|
||||||
// generated by go run gen.go -test; DO NOT EDIT
|
|
||||||
|
|
||||||
package atom
|
|
||||||
|
|
||||||
var testAtomList = []string{
|
|
||||||
"a",
|
|
||||||
"abbr",
|
|
||||||
"abbr",
|
|
||||||
"accept",
|
|
||||||
"accept-charset",
|
|
||||||
"accesskey",
|
|
||||||
"action",
|
|
||||||
"address",
|
|
||||||
"align",
|
|
||||||
"alt",
|
|
||||||
"annotation",
|
|
||||||
"annotation-xml",
|
|
||||||
"applet",
|
|
||||||
"area",
|
|
||||||
"article",
|
|
||||||
"aside",
|
|
||||||
"async",
|
|
||||||
"audio",
|
|
||||||
"autocomplete",
|
|
||||||
"autofocus",
|
|
||||||
"autoplay",
|
|
||||||
"b",
|
|
||||||
"base",
|
|
||||||
"basefont",
|
|
||||||
"bdi",
|
|
||||||
"bdo",
|
|
||||||
"bgsound",
|
|
||||||
"big",
|
|
||||||
"blink",
|
|
||||||
"blockquote",
|
|
||||||
"body",
|
|
||||||
"br",
|
|
||||||
"button",
|
|
||||||
"canvas",
|
|
||||||
"caption",
|
|
||||||
"center",
|
|
||||||
"challenge",
|
|
||||||
"charset",
|
|
||||||
"checked",
|
|
||||||
"cite",
|
|
||||||
"cite",
|
|
||||||
"class",
|
|
||||||
"code",
|
|
||||||
"col",
|
|
||||||
"colgroup",
|
|
||||||
"color",
|
|
||||||
"cols",
|
|
||||||
"colspan",
|
|
||||||
"command",
|
|
||||||
"command",
|
|
||||||
"content",
|
|
||||||
"contenteditable",
|
|
||||||
"contextmenu",
|
|
||||||
"controls",
|
|
||||||
"coords",
|
|
||||||
"crossorigin",
|
|
||||||
"data",
|
|
||||||
"data",
|
|
||||||
"datalist",
|
|
||||||
"datetime",
|
|
||||||
"dd",
|
|
||||||
"default",
|
|
||||||
"defer",
|
|
||||||
"del",
|
|
||||||
"desc",
|
|
||||||
"details",
|
|
||||||
"dfn",
|
|
||||||
"dialog",
|
|
||||||
"dir",
|
|
||||||
"dirname",
|
|
||||||
"disabled",
|
|
||||||
"div",
|
|
||||||
"dl",
|
|
||||||
"download",
|
|
||||||
"draggable",
|
|
||||||
"dropzone",
|
|
||||||
"dt",
|
|
||||||
"em",
|
|
||||||
"embed",
|
|
||||||
"enctype",
|
|
||||||
"face",
|
|
||||||
"fieldset",
|
|
||||||
"figcaption",
|
|
||||||
"figure",
|
|
||||||
"font",
|
|
||||||
"footer",
|
|
||||||
"for",
|
|
||||||
"foreignObject",
|
|
||||||
"foreignobject",
|
|
||||||
"form",
|
|
||||||
"form",
|
|
||||||
"formaction",
|
|
||||||
"formenctype",
|
|
||||||
"formmethod",
|
|
||||||
"formnovalidate",
|
|
||||||
"formtarget",
|
|
||||||
"frame",
|
|
||||||
"frameset",
|
|
||||||
"h1",
|
|
||||||
"h2",
|
|
||||||
"h3",
|
|
||||||
"h4",
|
|
||||||
"h5",
|
|
||||||
"h6",
|
|
||||||
"head",
|
|
||||||
"header",
|
|
||||||
"headers",
|
|
||||||
"height",
|
|
||||||
"hgroup",
|
|
||||||
"hidden",
|
|
||||||
"high",
|
|
||||||
"hr",
|
|
||||||
"href",
|
|
||||||
"hreflang",
|
|
||||||
"html",
|
|
||||||
"http-equiv",
|
|
||||||
"i",
|
|
||||||
"icon",
|
|
||||||
"id",
|
|
||||||
"iframe",
|
|
||||||
"image",
|
|
||||||
"img",
|
|
||||||
"input",
|
|
||||||
"inputmode",
|
|
||||||
"ins",
|
|
||||||
"isindex",
|
|
||||||
"ismap",
|
|
||||||
"itemid",
|
|
||||||
"itemprop",
|
|
||||||
"itemref",
|
|
||||||
"itemscope",
|
|
||||||
"itemtype",
|
|
||||||
"kbd",
|
|
||||||
"keygen",
|
|
||||||
"keytype",
|
|
||||||
"kind",
|
|
||||||
"label",
|
|
||||||
"label",
|
|
||||||
"lang",
|
|
||||||
"legend",
|
|
||||||
"li",
|
|
||||||
"link",
|
|
||||||
"list",
|
|
||||||
"listing",
|
|
||||||
"loop",
|
|
||||||
"low",
|
|
||||||
"malignmark",
|
|
||||||
"manifest",
|
|
||||||
"map",
|
|
||||||
"mark",
|
|
||||||
"marquee",
|
|
||||||
"math",
|
|
||||||
"max",
|
|
||||||
"maxlength",
|
|
||||||
"media",
|
|
||||||
"mediagroup",
|
|
||||||
"menu",
|
|
||||||
"menuitem",
|
|
||||||
"meta",
|
|
||||||
"meter",
|
|
||||||
"method",
|
|
||||||
"mglyph",
|
|
||||||
"mi",
|
|
||||||
"min",
|
|
||||||
"minlength",
|
|
||||||
"mn",
|
|
||||||
"mo",
|
|
||||||
"ms",
|
|
||||||
"mtext",
|
|
||||||
"multiple",
|
|
||||||
"muted",
|
|
||||||
"name",
|
|
||||||
"nav",
|
|
||||||
"nobr",
|
|
||||||
"noembed",
|
|
||||||
"noframes",
|
|
||||||
"noscript",
|
|
||||||
"novalidate",
|
|
||||||
"object",
|
|
||||||
"ol",
|
|
||||||
"onabort",
|
|
||||||
"onafterprint",
|
|
||||||
"onautocomplete",
|
|
||||||
"onautocompleteerror",
|
|
||||||
"onbeforeprint",
|
|
||||||
"onbeforeunload",
|
|
||||||
"onblur",
|
|
||||||
"oncancel",
|
|
||||||
"oncanplay",
|
|
||||||
"oncanplaythrough",
|
|
||||||
"onchange",
|
|
||||||
"onclick",
|
|
||||||
"onclose",
|
|
||||||
"oncontextmenu",
|
|
||||||
"oncuechange",
|
|
||||||
"ondblclick",
|
|
||||||
"ondrag",
|
|
||||||
"ondragend",
|
|
||||||
"ondragenter",
|
|
||||||
"ondragleave",
|
|
||||||
"ondragover",
|
|
||||||
"ondragstart",
|
|
||||||
"ondrop",
|
|
||||||
"ondurationchange",
|
|
||||||
"onemptied",
|
|
||||||
"onended",
|
|
||||||
"onerror",
|
|
||||||
"onfocus",
|
|
||||||
"onhashchange",
|
|
||||||
"oninput",
|
|
||||||
"oninvalid",
|
|
||||||
"onkeydown",
|
|
||||||
"onkeypress",
|
|
||||||
"onkeyup",
|
|
||||||
"onlanguagechange",
|
|
||||||
"onload",
|
|
||||||
"onloadeddata",
|
|
||||||
"onloadedmetadata",
|
|
||||||
"onloadstart",
|
|
||||||
"onmessage",
|
|
||||||
"onmousedown",
|
|
||||||
"onmousemove",
|
|
||||||
"onmouseout",
|
|
||||||
"onmouseover",
|
|
||||||
"onmouseup",
|
|
||||||
"onmousewheel",
|
|
||||||
"onoffline",
|
|
||||||
"ononline",
|
|
||||||
"onpagehide",
|
|
||||||
"onpageshow",
|
|
||||||
"onpause",
|
|
||||||
"onplay",
|
|
||||||
"onplaying",
|
|
||||||
"onpopstate",
|
|
||||||
"onprogress",
|
|
||||||
"onratechange",
|
|
||||||
"onreset",
|
|
||||||
"onresize",
|
|
||||||
"onscroll",
|
|
||||||
"onseeked",
|
|
||||||
"onseeking",
|
|
||||||
"onselect",
|
|
||||||
"onshow",
|
|
||||||
"onsort",
|
|
||||||
"onstalled",
|
|
||||||
"onstorage",
|
|
||||||
"onsubmit",
|
|
||||||
"onsuspend",
|
|
||||||
"ontimeupdate",
|
|
||||||
"ontoggle",
|
|
||||||
"onunload",
|
|
||||||
"onvolumechange",
|
|
||||||
"onwaiting",
|
|
||||||
"open",
|
|
||||||
"optgroup",
|
|
||||||
"optimum",
|
|
||||||
"option",
|
|
||||||
"output",
|
|
||||||
"p",
|
|
||||||
"param",
|
|
||||||
"pattern",
|
|
||||||
"ping",
|
|
||||||
"placeholder",
|
|
||||||
"plaintext",
|
|
||||||
"poster",
|
|
||||||
"pre",
|
|
||||||
"preload",
|
|
||||||
"progress",
|
|
||||||
"prompt",
|
|
||||||
"public",
|
|
||||||
"q",
|
|
||||||
"radiogroup",
|
|
||||||
"readonly",
|
|
||||||
"rel",
|
|
||||||
"required",
|
|
||||||
"reversed",
|
|
||||||
"rows",
|
|
||||||
"rowspan",
|
|
||||||
"rp",
|
|
||||||
"rt",
|
|
||||||
"ruby",
|
|
||||||
"s",
|
|
||||||
"samp",
|
|
||||||
"sandbox",
|
|
||||||
"scope",
|
|
||||||
"scoped",
|
|
||||||
"script",
|
|
||||||
"seamless",
|
|
||||||
"section",
|
|
||||||
"select",
|
|
||||||
"selected",
|
|
||||||
"shape",
|
|
||||||
"size",
|
|
||||||
"sizes",
|
|
||||||
"small",
|
|
||||||
"sortable",
|
|
||||||
"sorted",
|
|
||||||
"source",
|
|
||||||
"spacer",
|
|
||||||
"span",
|
|
||||||
"span",
|
|
||||||
"spellcheck",
|
|
||||||
"src",
|
|
||||||
"srcdoc",
|
|
||||||
"srclang",
|
|
||||||
"start",
|
|
||||||
"step",
|
|
||||||
"strike",
|
|
||||||
"strong",
|
|
||||||
"style",
|
|
||||||
"style",
|
|
||||||
"sub",
|
|
||||||
"summary",
|
|
||||||
"sup",
|
|
||||||
"svg",
|
|
||||||
"system",
|
|
||||||
"tabindex",
|
|
||||||
"table",
|
|
||||||
"target",
|
|
||||||
"tbody",
|
|
||||||
"td",
|
|
||||||
"template",
|
|
||||||
"textarea",
|
|
||||||
"tfoot",
|
|
||||||
"th",
|
|
||||||
"thead",
|
|
||||||
"time",
|
|
||||||
"title",
|
|
||||||
"title",
|
|
||||||
"tr",
|
|
||||||
"track",
|
|
||||||
"translate",
|
|
||||||
"tt",
|
|
||||||
"type",
|
|
||||||
"typemustmatch",
|
|
||||||
"u",
|
|
||||||
"ul",
|
|
||||||
"usemap",
|
|
||||||
"value",
|
|
||||||
"var",
|
|
||||||
"video",
|
|
||||||
"wbr",
|
|
||||||
"width",
|
|
||||||
"wrap",
|
|
||||||
"xmp",
|
|
||||||
}
|
|
236
Godeps/_workspace/src/golang.org/x/net/html/charset/charset_test.go
generated
vendored
236
Godeps/_workspace/src/golang.org/x/net/html/charset/charset_test.go
generated
vendored
|
@ -1,236 +0,0 @@
|
||||||
// Copyright 2013 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.
|
|
||||||
|
|
||||||
package charset
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"encoding/xml"
|
|
||||||
"io/ioutil"
|
|
||||||
"runtime"
|
|
||||||
"strings"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"golang.org/x/text/transform"
|
|
||||||
)
|
|
||||||
|
|
||||||
func transformString(t transform.Transformer, s string) (string, error) {
|
|
||||||
r := transform.NewReader(strings.NewReader(s), t)
|
|
||||||
b, err := ioutil.ReadAll(r)
|
|
||||||
return string(b), err
|
|
||||||
}
|
|
||||||
|
|
||||||
var testCases = []struct {
|
|
||||||
utf8, other, otherEncoding string
|
|
||||||
}{
|
|
||||||
{"Résumé", "Résumé", "utf8"},
|
|
||||||
{"Résumé", "R\xe9sum\xe9", "latin1"},
|
|
||||||
{"これは漢字です。", "S0\x8c0o0\"oW[g0Y0\x020", "UTF-16LE"},
|
|
||||||
{"これは漢字です。", "0S0\x8c0oo\"[W0g0Y0\x02", "UTF-16BE"},
|
|
||||||
{"Hello, world", "Hello, world", "ASCII"},
|
|
||||||
{"Gdańsk", "Gda\xf1sk", "ISO-8859-2"},
|
|
||||||
{"Ââ Čč Đđ Ŋŋ Õõ Šš Žž Åå Ää", "\xc2\xe2 \xc8\xe8 \xa9\xb9 \xaf\xbf \xd5\xf5 \xaa\xba \xac\xbc \xc5\xe5 \xc4\xe4", "ISO-8859-10"},
|
|
||||||
{"สำหรับ", "\xca\xd3\xcb\xc3\u047a", "ISO-8859-11"},
|
|
||||||
{"latviešu", "latvie\xf0u", "ISO-8859-13"},
|
|
||||||
{"Seònaid", "Se\xf2naid", "ISO-8859-14"},
|
|
||||||
{"€1 is cheap", "\xa41 is cheap", "ISO-8859-15"},
|
|
||||||
{"românește", "rom\xe2ne\xbate", "ISO-8859-16"},
|
|
||||||
{"nutraĵo", "nutra\xbco", "ISO-8859-3"},
|
|
||||||
{"Kalâdlit", "Kal\xe2dlit", "ISO-8859-4"},
|
|
||||||
{"русский", "\xe0\xe3\xe1\xe1\xda\xd8\xd9", "ISO-8859-5"},
|
|
||||||
{"ελληνικά", "\xe5\xeb\xeb\xe7\xed\xe9\xea\xdc", "ISO-8859-7"},
|
|
||||||
{"Kağan", "Ka\xf0an", "ISO-8859-9"},
|
|
||||||
{"Résumé", "R\x8esum\x8e", "macintosh"},
|
|
||||||
{"Gdańsk", "Gda\xf1sk", "windows-1250"},
|
|
||||||
{"русский", "\xf0\xf3\xf1\xf1\xea\xe8\xe9", "windows-1251"},
|
|
||||||
{"Résumé", "R\xe9sum\xe9", "windows-1252"},
|
|
||||||
{"ελληνικά", "\xe5\xeb\xeb\xe7\xed\xe9\xea\xdc", "windows-1253"},
|
|
||||||
{"Kağan", "Ka\xf0an", "windows-1254"},
|
|
||||||
{"עִבְרִית", "\xf2\xc4\xe1\xc0\xf8\xc4\xe9\xfa", "windows-1255"},
|
|
||||||
{"العربية", "\xc7\xe1\xda\xd1\xc8\xed\xc9", "windows-1256"},
|
|
||||||
{"latviešu", "latvie\xf0u", "windows-1257"},
|
|
||||||
{"Việt", "Vi\xea\xf2t", "windows-1258"},
|
|
||||||
{"สำหรับ", "\xca\xd3\xcb\xc3\u047a", "windows-874"},
|
|
||||||
{"русский", "\xd2\xd5\xd3\xd3\xcb\xc9\xca", "KOI8-R"},
|
|
||||||
{"українська", "\xd5\xcb\xd2\xc1\xa7\xce\xd3\xd8\xcb\xc1", "KOI8-U"},
|
|
||||||
{"Hello 常用國字標準字體表", "Hello \xb1`\xa5\u03b0\xea\xa6r\xbc\u0437\u01e6r\xc5\xe9\xaa\xed", "big5"},
|
|
||||||
{"Hello 常用國字標準字體表", "Hello \xb3\xa3\xd3\xc3\x87\xf8\xd7\xd6\x98\xcb\x9c\xca\xd7\xd6\xf3\x77\xb1\xed", "gbk"},
|
|
||||||
{"Hello 常用國字標準字體表", "Hello \xb3\xa3\xd3\xc3\x87\xf8\xd7\xd6\x98\xcb\x9c\xca\xd7\xd6\xf3\x77\xb1\xed", "gb18030"},
|
|
||||||
{"עִבְרִית", "\x81\x30\xfb\x30\x81\x30\xf6\x34\x81\x30\xf9\x33\x81\x30\xf6\x30\x81\x30\xfb\x36\x81\x30\xf6\x34\x81\x30\xfa\x31\x81\x30\xfb\x38", "gb18030"},
|
|
||||||
{"㧯", "\x82\x31\x89\x38", "gb18030"},
|
|
||||||
{"これは漢字です。", "\x82\xb1\x82\xea\x82\xcd\x8a\xbf\x8e\x9a\x82\xc5\x82\xb7\x81B", "SJIS"},
|
|
||||||
{"Hello, 世界!", "Hello, \x90\xa2\x8aE!", "SJIS"},
|
|
||||||
{"イウエオカ", "\xb2\xb3\xb4\xb5\xb6", "SJIS"},
|
|
||||||
{"これは漢字です。", "\xa4\xb3\xa4\xec\xa4\u03f4\xc1\xbb\xfa\xa4\u01e4\xb9\xa1\xa3", "EUC-JP"},
|
|
||||||
{"Hello, 世界!", "Hello, \x1b$B@$3&\x1b(B!", "ISO-2022-JP"},
|
|
||||||
{"네이트 | 즐거움의 시작, 슈파스(Spaβ) NATE", "\xb3\xd7\xc0\xcc\xc6\xae | \xc1\xf1\xb0\xc5\xbf\xf2\xc0\xc7 \xbd\xc3\xc0\xdb, \xbd\xb4\xc6\xc4\xbd\xba(Spa\xa5\xe2) NATE", "EUC-KR"},
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestDecode(t *testing.T) {
|
|
||||||
for _, tc := range testCases {
|
|
||||||
e, _ := Lookup(tc.otherEncoding)
|
|
||||||
if e == nil {
|
|
||||||
t.Errorf("%s: not found", tc.otherEncoding)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
s, err := transformString(e.NewDecoder(), tc.other)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("%s: decode %q: %v", tc.otherEncoding, tc.other, err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if s != tc.utf8 {
|
|
||||||
t.Errorf("%s: got %q, want %q", tc.otherEncoding, s, tc.utf8)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestEncode(t *testing.T) {
|
|
||||||
for _, tc := range testCases {
|
|
||||||
e, _ := Lookup(tc.otherEncoding)
|
|
||||||
if e == nil {
|
|
||||||
t.Errorf("%s: not found", tc.otherEncoding)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
s, err := transformString(e.NewEncoder(), tc.utf8)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("%s: encode %q: %s", tc.otherEncoding, tc.utf8, err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if s != tc.other {
|
|
||||||
t.Errorf("%s: got %q, want %q", tc.otherEncoding, s, tc.other)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TestNames verifies that you can pass an encoding's name to Lookup and get
|
|
||||||
// the same encoding back (except for "replacement").
|
|
||||||
func TestNames(t *testing.T) {
|
|
||||||
for _, e := range encodings {
|
|
||||||
if e.name == "replacement" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
_, got := Lookup(e.name)
|
|
||||||
if got != e.name {
|
|
||||||
t.Errorf("got %q, want %q", got, e.name)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var sniffTestCases = []struct {
|
|
||||||
filename, declared, want string
|
|
||||||
}{
|
|
||||||
{"HTTP-charset.html", "text/html; charset=iso-8859-15", "iso-8859-15"},
|
|
||||||
{"UTF-16LE-BOM.html", "", "utf-16le"},
|
|
||||||
{"UTF-16BE-BOM.html", "", "utf-16be"},
|
|
||||||
{"meta-content-attribute.html", "text/html", "iso-8859-15"},
|
|
||||||
{"meta-charset-attribute.html", "text/html", "iso-8859-15"},
|
|
||||||
{"No-encoding-declaration.html", "text/html", "utf-8"},
|
|
||||||
{"HTTP-vs-UTF-8-BOM.html", "text/html; charset=iso-8859-15", "utf-8"},
|
|
||||||
{"HTTP-vs-meta-content.html", "text/html; charset=iso-8859-15", "iso-8859-15"},
|
|
||||||
{"HTTP-vs-meta-charset.html", "text/html; charset=iso-8859-15", "iso-8859-15"},
|
|
||||||
{"UTF-8-BOM-vs-meta-content.html", "text/html", "utf-8"},
|
|
||||||
{"UTF-8-BOM-vs-meta-charset.html", "text/html", "utf-8"},
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSniff(t *testing.T) {
|
|
||||||
switch runtime.GOOS {
|
|
||||||
case "nacl": // platforms that don't permit direct file system access
|
|
||||||
t.Skipf("not supported on %q", runtime.GOOS)
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, tc := range sniffTestCases {
|
|
||||||
content, err := ioutil.ReadFile("testdata/" + tc.filename)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("%s: error reading file: %v", tc.filename, err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
_, name, _ := DetermineEncoding(content, tc.declared)
|
|
||||||
if name != tc.want {
|
|
||||||
t.Errorf("%s: got %q, want %q", tc.filename, name, tc.want)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestReader(t *testing.T) {
|
|
||||||
switch runtime.GOOS {
|
|
||||||
case "nacl": // platforms that don't permit direct file system access
|
|
||||||
t.Skipf("not supported on %q", runtime.GOOS)
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, tc := range sniffTestCases {
|
|
||||||
content, err := ioutil.ReadFile("testdata/" + tc.filename)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("%s: error reading file: %v", tc.filename, err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
r, err := NewReader(bytes.NewReader(content), tc.declared)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("%s: error creating reader: %v", tc.filename, err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
got, err := ioutil.ReadAll(r)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("%s: error reading from charset.NewReader: %v", tc.filename, err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
e, _ := Lookup(tc.want)
|
|
||||||
want, err := ioutil.ReadAll(transform.NewReader(bytes.NewReader(content), e.NewDecoder()))
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("%s: error decoding with hard-coded charset name: %v", tc.filename, err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if !bytes.Equal(got, want) {
|
|
||||||
t.Errorf("%s: got %q, want %q", tc.filename, got, want)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var metaTestCases = []struct {
|
|
||||||
meta, want string
|
|
||||||
}{
|
|
||||||
{"", ""},
|
|
||||||
{"text/html", ""},
|
|
||||||
{"text/html; charset utf-8", ""},
|
|
||||||
{"text/html; charset=latin-2", "latin-2"},
|
|
||||||
{"text/html; charset; charset = utf-8", "utf-8"},
|
|
||||||
{`charset="big5"`, "big5"},
|
|
||||||
{"charset='shift_jis'", "shift_jis"},
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFromMeta(t *testing.T) {
|
|
||||||
for _, tc := range metaTestCases {
|
|
||||||
got := fromMetaElement(tc.meta)
|
|
||||||
if got != tc.want {
|
|
||||||
t.Errorf("%q: got %q, want %q", tc.meta, got, tc.want)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestXML(t *testing.T) {
|
|
||||||
const s = "<?xml version=\"1.0\" encoding=\"windows-1252\"?><a><Word>r\xe9sum\xe9</Word></a>"
|
|
||||||
|
|
||||||
d := xml.NewDecoder(strings.NewReader(s))
|
|
||||||
d.CharsetReader = NewReaderLabel
|
|
||||||
|
|
||||||
var a struct {
|
|
||||||
Word string
|
|
||||||
}
|
|
||||||
err := d.Decode(&a)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Decode: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
want := "résumé"
|
|
||||||
if a.Word != want {
|
|
||||||
t.Errorf("got %q, want %q", a.Word, want)
|
|
||||||
}
|
|
||||||
}
|
|
48
Godeps/_workspace/src/golang.org/x/net/html/charset/testdata/HTTP-charset.html
generated
vendored
48
Godeps/_workspace/src/golang.org/x/net/html/charset/testdata/HTTP-charset.html
generated
vendored
|
@ -1,48 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en" >
|
|
||||||
<head>
|
|
||||||
<title>HTTP charset</title>
|
|
||||||
<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'>
|
|
||||||
<link rel='help' href='http://www.w3.org/TR/html5/syntax.html#the-input-byte-stream'>
|
|
||||||
<link rel="stylesheet" type="text/css" href="./generatedtests.css">
|
|
||||||
<script src="http://w3c-test.org/resources/testharness.js"></script>
|
|
||||||
<script src="http://w3c-test.org/resources/testharnessreport.js"></script>
|
|
||||||
<meta name='flags' content='http'>
|
|
||||||
<meta name="assert" content="The character encoding of a page can be set using the HTTP header charset declaration.">
|
|
||||||
<style type='text/css'>
|
|
||||||
.test div { width: 50px; }</style>
|
|
||||||
<link rel="stylesheet" type="text/css" href="the-input-byte-stream/support/encodingtests-15.css">
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<p class='title'>HTTP charset</p>
|
|
||||||
|
|
||||||
|
|
||||||
<div id='log'></div>
|
|
||||||
|
|
||||||
|
|
||||||
<div class='test'><div id='box' class='ýäè'> </div></div>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div class='description'>
|
|
||||||
<p class="assertion" title="Assertion">The character encoding of a page can be set using the HTTP header charset declaration.</p>
|
|
||||||
<div class="notes"><p><p>The test contains a div with a class name that contains the following sequence of bytes: 0xC3 0xBD 0xC3 0xA4 0xC3 0xA8. These represent different sequences of characters in ISO 8859-15, ISO 8859-1 and UTF-8. The external, UTF-8-encoded stylesheet contains a selector <code>.test div.ÜÀÚ</code>. This matches the sequence of bytes above when they are interpreted as ISO 8859-15. If the class name matches the selector then the test will pass.</p><p>The only character encoding declaration for this HTML file is in the HTTP header, which sets the encoding to ISO 8859-15.</p></p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="nexttest"><div><a href="generate?test=the-input-byte-stream-003">Next test</a></div><div class="doctype">HTML5</div>
|
|
||||||
<p class="jump">the-input-byte-stream-001<br /><a href="/International/tests/html5/the-input-byte-stream/results-basics#basics" target="_blank">Result summary & related tests</a><br /><a href="http://w3c-test.org/framework/details/i18n-html5/the-input-byte-stream-001" target="_blank">Detailed results for this test</a><br/> <a href="http://www.w3.org/TR/html5/syntax.html#the-input-byte-stream" target="_blank">Link to spec</a></p>
|
|
||||||
<div class='prereq'>Assumptions: <ul><li>The default encoding for the browser you are testing is not set to ISO 8859-15.</li>
|
|
||||||
<li>The test is read from a server that supports HTTP.</li></ul></div>
|
|
||||||
</div>
|
|
||||||
<script>
|
|
||||||
test(function() {
|
|
||||||
assert_equals(document.getElementById('box').offsetWidth, 100);
|
|
||||||
}, " ");
|
|
||||||
</script>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
|
|
||||||
|
|
48
Godeps/_workspace/src/golang.org/x/net/html/charset/testdata/HTTP-vs-UTF-8-BOM.html
generated
vendored
48
Godeps/_workspace/src/golang.org/x/net/html/charset/testdata/HTTP-vs-UTF-8-BOM.html
generated
vendored
|
@ -1,48 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en" >
|
|
||||||
<head>
|
|
||||||
<title>HTTP vs UTF-8 BOM</title>
|
|
||||||
<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'>
|
|
||||||
<link rel='help' href='http://www.w3.org/TR/html5/syntax.html#the-input-byte-stream'>
|
|
||||||
<link rel="stylesheet" type="text/css" href="./generatedtests.css">
|
|
||||||
<script src="http://w3c-test.org/resources/testharness.js"></script>
|
|
||||||
<script src="http://w3c-test.org/resources/testharnessreport.js"></script>
|
|
||||||
<meta name='flags' content='http'>
|
|
||||||
<meta name="assert" content="A character encoding set in the HTTP header has lower precedence than the UTF-8 signature.">
|
|
||||||
<style type='text/css'>
|
|
||||||
.test div { width: 50px; }</style>
|
|
||||||
<link rel="stylesheet" type="text/css" href="the-input-byte-stream/support/encodingtests-utf8.css">
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<p class='title'>HTTP vs UTF-8 BOM</p>
|
|
||||||
|
|
||||||
|
|
||||||
<div id='log'></div>
|
|
||||||
|
|
||||||
|
|
||||||
<div class='test'><div id='box' class='ýäè'> </div></div>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div class='description'>
|
|
||||||
<p class="assertion" title="Assertion">A character encoding set in the HTTP header has lower precedence than the UTF-8 signature.</p>
|
|
||||||
<div class="notes"><p><p>The HTTP header attempts to set the character encoding to ISO 8859-15. The page starts with a UTF-8 signature.</p><p>The test contains a div with a class name that contains the following sequence of bytes: 0xC3 0xBD 0xC3 0xA4 0xC3 0xA8. These represent different sequences of characters in ISO 8859-15, ISO 8859-1 and UTF-8. The external, UTF-8-encoded stylesheet contains a selector <code>.test div.ýäè</code>. This matches the sequence of bytes above when they are interpreted as UTF-8. If the class name matches the selector then the test will pass.</p><p>If the test is unsuccessful, the characters  should appear at the top of the page. These represent the bytes that make up the UTF-8 signature when encountered in the ISO 8859-15 encoding.</p></p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="nexttest"><div><a href="generate?test=the-input-byte-stream-022">Next test</a></div><div class="doctype">HTML5</div>
|
|
||||||
<p class="jump">the-input-byte-stream-034<br /><a href="/International/tests/html5/the-input-byte-stream/results-basics#precedence" target="_blank">Result summary & related tests</a><br /><a href="http://w3c-test.org/framework/details/i18n-html5/the-input-byte-stream-034" target="_blank">Detailed results for this test</a><br/> <a href="http://www.w3.org/TR/html5/syntax.html#the-input-byte-stream" target="_blank">Link to spec</a></p>
|
|
||||||
<div class='prereq'>Assumptions: <ul><li>The default encoding for the browser you are testing is not set to ISO 8859-15.</li>
|
|
||||||
<li>The test is read from a server that supports HTTP.</li></ul></div>
|
|
||||||
</div>
|
|
||||||
<script>
|
|
||||||
test(function() {
|
|
||||||
assert_equals(document.getElementById('box').offsetWidth, 100);
|
|
||||||
}, " ");
|
|
||||||
</script>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
|
|
||||||
|
|
49
Godeps/_workspace/src/golang.org/x/net/html/charset/testdata/HTTP-vs-meta-charset.html
generated
vendored
49
Godeps/_workspace/src/golang.org/x/net/html/charset/testdata/HTTP-vs-meta-charset.html
generated
vendored
|
@ -1,49 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en" >
|
|
||||||
<head>
|
|
||||||
<meta charset="iso-8859-1" > <title>HTTP vs meta charset</title>
|
|
||||||
<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'>
|
|
||||||
<link rel='help' href='http://www.w3.org/TR/html5/syntax.html#the-input-byte-stream'>
|
|
||||||
<link rel="stylesheet" type="text/css" href="./generatedtests.css">
|
|
||||||
<script src="http://w3c-test.org/resources/testharness.js"></script>
|
|
||||||
<script src="http://w3c-test.org/resources/testharnessreport.js"></script>
|
|
||||||
<meta name='flags' content='http'>
|
|
||||||
<meta name="assert" content="The HTTP header has a higher precedence than an encoding declaration in a meta charset attribute.">
|
|
||||||
<style type='text/css'>
|
|
||||||
.test div { width: 50px; }.test div { width: 90px; }
|
|
||||||
</style>
|
|
||||||
<link rel="stylesheet" type="text/css" href="the-input-byte-stream/support/encodingtests-15.css">
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<p class='title'>HTTP vs meta charset</p>
|
|
||||||
|
|
||||||
|
|
||||||
<div id='log'></div>
|
|
||||||
|
|
||||||
|
|
||||||
<div class='test'><div id='box' class='ýäè'> </div></div>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div class='description'>
|
|
||||||
<p class="assertion" title="Assertion">The HTTP header has a higher precedence than an encoding declaration in a meta charset attribute.</p>
|
|
||||||
<div class="notes"><p><p>The HTTP header attempts to set the character encoding to ISO 8859-15. The page contains an encoding declaration in a meta charset attribute that attempts to set the character encoding to ISO 8859-1.</p><p>The test contains a div with a class name that contains the following sequence of bytes: 0xC3 0xBD 0xC3 0xA4 0xC3 0xA8. These represent different sequences of characters in ISO 8859-15, ISO 8859-1 and UTF-8. The external, UTF-8-encoded stylesheet contains a selector <code>.test div.ÜÀÚ</code>. This matches the sequence of bytes above when they are interpreted as ISO 8859-15. If the class name matches the selector then the test will pass.</p></p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="nexttest"><div><a href="generate?test=the-input-byte-stream-037">Next test</a></div><div class="doctype">HTML5</div>
|
|
||||||
<p class="jump">the-input-byte-stream-018<br /><a href="/International/tests/html5/the-input-byte-stream/results-basics#precedence" target="_blank">Result summary & related tests</a><br /><a href="http://w3c-test.org/framework/details/i18n-html5/the-input-byte-stream-018" target="_blank">Detailed results for this test</a><br/> <a href="http://www.w3.org/TR/html5/syntax.html#the-input-byte-stream" target="_blank">Link to spec</a></p>
|
|
||||||
<div class='prereq'>Assumptions: <ul><li>The default encoding for the browser you are testing is not set to ISO 8859-15.</li>
|
|
||||||
<li>The test is read from a server that supports HTTP.</li></ul></div>
|
|
||||||
</div>
|
|
||||||
<script>
|
|
||||||
test(function() {
|
|
||||||
assert_equals(document.getElementById('box').offsetWidth, 100);
|
|
||||||
}, " ");
|
|
||||||
</script>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
|
|
||||||
|
|
49
Godeps/_workspace/src/golang.org/x/net/html/charset/testdata/HTTP-vs-meta-content.html
generated
vendored
49
Godeps/_workspace/src/golang.org/x/net/html/charset/testdata/HTTP-vs-meta-content.html
generated
vendored
|
@ -1,49 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en" >
|
|
||||||
<head>
|
|
||||||
<meta http-equiv="content-type" content="text/html;charset=iso-8859-1" > <title>HTTP vs meta content</title>
|
|
||||||
<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'>
|
|
||||||
<link rel='help' href='http://www.w3.org/TR/html5/syntax.html#the-input-byte-stream'>
|
|
||||||
<link rel="stylesheet" type="text/css" href="./generatedtests.css">
|
|
||||||
<script src="http://w3c-test.org/resources/testharness.js"></script>
|
|
||||||
<script src="http://w3c-test.org/resources/testharnessreport.js"></script>
|
|
||||||
<meta name='flags' content='http'>
|
|
||||||
<meta name="assert" content="The HTTP header has a higher precedence than an encoding declaration in a meta content attribute.">
|
|
||||||
<style type='text/css'>
|
|
||||||
.test div { width: 50px; }.test div { width: 90px; }
|
|
||||||
</style>
|
|
||||||
<link rel="stylesheet" type="text/css" href="the-input-byte-stream/support/encodingtests-15.css">
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<p class='title'>HTTP vs meta content</p>
|
|
||||||
|
|
||||||
|
|
||||||
<div id='log'></div>
|
|
||||||
|
|
||||||
|
|
||||||
<div class='test'><div id='box' class='ýäè'> </div></div>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div class='description'>
|
|
||||||
<p class="assertion" title="Assertion">The HTTP header has a higher precedence than an encoding declaration in a meta content attribute.</p>
|
|
||||||
<div class="notes"><p><p>The HTTP header attempts to set the character encoding to ISO 8859-15. The page contains an encoding declaration in a meta content attribute that attempts to set the character encoding to ISO 8859-1.</p><p>The test contains a div with a class name that contains the following sequence of bytes: 0xC3 0xBD 0xC3 0xA4 0xC3 0xA8. These represent different sequences of characters in ISO 8859-15, ISO 8859-1 and UTF-8. The external, UTF-8-encoded stylesheet contains a selector <code>.test div.ÜÀÚ</code>. This matches the sequence of bytes above when they are interpreted as ISO 8859-15. If the class name matches the selector then the test will pass.</p></p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="nexttest"><div><a href="generate?test=the-input-byte-stream-018">Next test</a></div><div class="doctype">HTML5</div>
|
|
||||||
<p class="jump">the-input-byte-stream-016<br /><a href="/International/tests/html5/the-input-byte-stream/results-basics#precedence" target="_blank">Result summary & related tests</a><br /><a href="http://w3c-test.org/framework/details/i18n-html5/the-input-byte-stream-016" target="_blank">Detailed results for this test</a><br/> <a href="http://www.w3.org/TR/html5/syntax.html#the-input-byte-stream" target="_blank">Link to spec</a></p>
|
|
||||||
<div class='prereq'>Assumptions: <ul><li>The default encoding for the browser you are testing is not set to ISO 8859-15.</li>
|
|
||||||
<li>The test is read from a server that supports HTTP.</li></ul></div>
|
|
||||||
</div>
|
|
||||||
<script>
|
|
||||||
test(function() {
|
|
||||||
assert_equals(document.getElementById('box').offsetWidth, 100);
|
|
||||||
}, " ");
|
|
||||||
</script>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
|
|
||||||
|
|
|
@ -1,47 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en" >
|
|
||||||
<head>
|
|
||||||
<title>No encoding declaration</title>
|
|
||||||
<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'>
|
|
||||||
<link rel='help' href='http://www.w3.org/TR/html5/syntax.html#the-input-byte-stream'>
|
|
||||||
<link rel="stylesheet" type="text/css" href="./generatedtests.css">
|
|
||||||
<script src="http://w3c-test.org/resources/testharness.js"></script>
|
|
||||||
<script src="http://w3c-test.org/resources/testharnessreport.js"></script>
|
|
||||||
<meta name='flags' content='http'>
|
|
||||||
<meta name="assert" content="A page with no encoding information in HTTP, BOM, XML declaration or meta element will be treated as UTF-8.">
|
|
||||||
<style type='text/css'>
|
|
||||||
.test div { width: 50px; }</style>
|
|
||||||
<link rel="stylesheet" type="text/css" href="the-input-byte-stream/support/encodingtests-utf8.css">
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<p class='title'>No encoding declaration</p>
|
|
||||||
|
|
||||||
|
|
||||||
<div id='log'></div>
|
|
||||||
|
|
||||||
|
|
||||||
<div class='test'><div id='box' class='ýäè'> </div></div>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div class='description'>
|
|
||||||
<p class="assertion" title="Assertion">A page with no encoding information in HTTP, BOM, XML declaration or meta element will be treated as UTF-8.</p>
|
|
||||||
<div class="notes"><p><p>The test on this page contains a div with a class name that contains the following sequence of bytes: 0xC3 0xBD 0xC3 0xA4 0xC3 0xA8. These represent different sequences of characters in ISO 8859-15, ISO 8859-1 and UTF-8. The external, UTF-8-encoded stylesheet contains a selector <code>.test div.ýäè</code>. This matches the sequence of bytes above when they are interpreted as UTF-8. If the class name matches the selector then the test will pass.</p></p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="nexttest"><div><a href="generate?test=the-input-byte-stream-034">Next test</a></div><div class="doctype">HTML5</div>
|
|
||||||
<p class="jump">the-input-byte-stream-015<br /><a href="/International/tests/html5/the-input-byte-stream/results-basics#basics" target="_blank">Result summary & related tests</a><br /><a href="http://w3c-test.org/framework/details/i18n-html5/the-input-byte-stream-015" target="_blank">Detailed results for this test</a><br/> <a href="http://www.w3.org/TR/html5/syntax.html#the-input-byte-stream" target="_blank">Link to spec</a></p>
|
|
||||||
<div class='prereq'>Assumptions: <ul><li>The test is read from a server that supports HTTP.</li></ul></div>
|
|
||||||
</div>
|
|
||||||
<script>
|
|
||||||
test(function() {
|
|
||||||
assert_equals(document.getElementById('box').offsetWidth, 100);
|
|
||||||
}, " ");
|
|
||||||
</script>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
|
|
||||||
|
|
9
Godeps/_workspace/src/golang.org/x/net/html/charset/testdata/README
generated
vendored
9
Godeps/_workspace/src/golang.org/x/net/html/charset/testdata/README
generated
vendored
|
@ -1,9 +0,0 @@
|
||||||
These test cases come from
|
|
||||||
http://www.w3.org/International/tests/repository/html5/the-input-byte-stream/results-basics
|
|
||||||
|
|
||||||
Distributed under both the W3C Test Suite License
|
|
||||||
(http://www.w3.org/Consortium/Legal/2008/04-testsuite-license)
|
|
||||||
and the W3C 3-clause BSD License
|
|
||||||
(http://www.w3.org/Consortium/Legal/2008/03-bsd-license).
|
|
||||||
To contribute to a W3C Test Suite, see the policies and contribution
|
|
||||||
forms (http://www.w3.org/2004/10/27-testcases).
|
|
BIN
Godeps/_workspace/src/golang.org/x/net/html/charset/testdata/UTF-16BE-BOM.html
generated
vendored
BIN
Godeps/_workspace/src/golang.org/x/net/html/charset/testdata/UTF-16BE-BOM.html
generated
vendored
Binary file not shown.
BIN
Godeps/_workspace/src/golang.org/x/net/html/charset/testdata/UTF-16LE-BOM.html
generated
vendored
BIN
Godeps/_workspace/src/golang.org/x/net/html/charset/testdata/UTF-16LE-BOM.html
generated
vendored
Binary file not shown.
|
@ -1,49 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en" >
|
|
||||||
<head>
|
|
||||||
<meta charset="iso-8859-15"> <title>UTF-8 BOM vs meta charset</title>
|
|
||||||
<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'>
|
|
||||||
<link rel='help' href='http://www.w3.org/TR/html5/syntax.html#the-input-byte-stream'>
|
|
||||||
<link rel="stylesheet" type="text/css" href="./generatedtests.css">
|
|
||||||
<script src="http://w3c-test.org/resources/testharness.js"></script>
|
|
||||||
<script src="http://w3c-test.org/resources/testharnessreport.js"></script>
|
|
||||||
<meta name='flags' content='http'>
|
|
||||||
<meta name="assert" content="A page with a UTF-8 BOM will be recognized as UTF-8 even if the meta charset attribute declares a different encoding.">
|
|
||||||
<style type='text/css'>
|
|
||||||
.test div { width: 50px; }.test div { width: 90px; }
|
|
||||||
</style>
|
|
||||||
<link rel="stylesheet" type="text/css" href="the-input-byte-stream/support/encodingtests-utf8.css">
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<p class='title'>UTF-8 BOM vs meta charset</p>
|
|
||||||
|
|
||||||
|
|
||||||
<div id='log'></div>
|
|
||||||
|
|
||||||
|
|
||||||
<div class='test'><div id='box' class='ýäè'> </div></div>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div class='description'>
|
|
||||||
<p class="assertion" title="Assertion">A page with a UTF-8 BOM will be recognized as UTF-8 even if the meta charset attribute declares a different encoding.</p>
|
|
||||||
<div class="notes"><p><p>The page contains an encoding declaration in a meta charset attribute that attempts to set the character encoding to ISO 8859-15, but the file starts with a UTF-8 signature.</p><p>The test contains a div with a class name that contains the following sequence of bytes: 0xC3 0xBD 0xC3 0xA4 0xC3 0xA8. These represent different sequences of characters in ISO 8859-15, ISO 8859-1 and UTF-8. The external, UTF-8-encoded stylesheet contains a selector <code>.test div.ýäè</code>. This matches the sequence of bytes above when they are interpreted as UTF-8. If the class name matches the selector then the test will pass.</p></p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="nexttest"><div><a href="generate?test=the-input-byte-stream-024">Next test</a></div><div class="doctype">HTML5</div>
|
|
||||||
<p class="jump">the-input-byte-stream-038<br /><a href="/International/tests/html5/the-input-byte-stream/results-basics#precedence" target="_blank">Result summary & related tests</a><br /><a href="http://w3c-test.org/framework/details/i18n-html5/the-input-byte-stream-038" target="_blank">Detailed results for this test</a><br/> <a href="http://www.w3.org/TR/html5/syntax.html#the-input-byte-stream" target="_blank">Link to spec</a></p>
|
|
||||||
<div class='prereq'>Assumptions: <ul><li>The default encoding for the browser you are testing is not set to ISO 8859-15.</li>
|
|
||||||
<li>The test is read from a server that supports HTTP.</li></ul></div>
|
|
||||||
</div>
|
|
||||||
<script>
|
|
||||||
test(function() {
|
|
||||||
assert_equals(document.getElementById('box').offsetWidth, 100);
|
|
||||||
}, " ");
|
|
||||||
</script>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
|
|
||||||
|
|
|
@ -1,48 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en" >
|
|
||||||
<head>
|
|
||||||
<meta http-equiv="content-type" content="text/html; charset=iso-8859-15"> <title>UTF-8 BOM vs meta content</title>
|
|
||||||
<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'>
|
|
||||||
<link rel='help' href='http://www.w3.org/TR/html5/syntax.html#the-input-byte-stream'>
|
|
||||||
<link rel="stylesheet" type="text/css" href="./generatedtests.css">
|
|
||||||
<script src="http://w3c-test.org/resources/testharness.js"></script>
|
|
||||||
<script src="http://w3c-test.org/resources/testharnessreport.js"></script>
|
|
||||||
<meta name='flags' content='http'>
|
|
||||||
<meta name="assert" content="A page with a UTF-8 BOM will be recognized as UTF-8 even if the meta content attribute declares a different encoding.">
|
|
||||||
<style type='text/css'>
|
|
||||||
.test div { width: 50px; }</style>
|
|
||||||
<link rel="stylesheet" type="text/css" href="the-input-byte-stream/support/encodingtests-utf8.css">
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<p class='title'>UTF-8 BOM vs meta content</p>
|
|
||||||
|
|
||||||
|
|
||||||
<div id='log'></div>
|
|
||||||
|
|
||||||
|
|
||||||
<div class='test'><div id='box' class='ýäè'> </div></div>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div class='description'>
|
|
||||||
<p class="assertion" title="Assertion">A page with a UTF-8 BOM will be recognized as UTF-8 even if the meta content attribute declares a different encoding.</p>
|
|
||||||
<div class="notes"><p><p>The page contains an encoding declaration in a meta content attribute that attempts to set the character encoding to ISO 8859-15, but the file starts with a UTF-8 signature.</p><p>The test contains a div with a class name that contains the following sequence of bytes: 0xC3 0xBD 0xC3 0xA4 0xC3 0xA8. These represent different sequences of characters in ISO 8859-15, ISO 8859-1 and UTF-8. The external, UTF-8-encoded stylesheet contains a selector <code>.test div.ýäè</code>. This matches the sequence of bytes above when they are interpreted as UTF-8. If the class name matches the selector then the test will pass.</p></p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="nexttest"><div><a href="generate?test=the-input-byte-stream-038">Next test</a></div><div class="doctype">HTML5</div>
|
|
||||||
<p class="jump">the-input-byte-stream-037<br /><a href="/International/tests/html5/the-input-byte-stream/results-basics#precedence" target="_blank">Result summary & related tests</a><br /><a href="http://w3c-test.org/framework/details/i18n-html5/the-input-byte-stream-037" target="_blank">Detailed results for this test</a><br/> <a href="http://www.w3.org/TR/html5/syntax.html#the-input-byte-stream" target="_blank">Link to spec</a></p>
|
|
||||||
<div class='prereq'>Assumptions: <ul><li>The default encoding for the browser you are testing is not set to ISO 8859-15.</li>
|
|
||||||
<li>The test is read from a server that supports HTTP.</li></ul></div>
|
|
||||||
</div>
|
|
||||||
<script>
|
|
||||||
test(function() {
|
|
||||||
assert_equals(document.getElementById('box').offsetWidth, 100);
|
|
||||||
}, " ");
|
|
||||||
</script>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
|
|
||||||
|
|
48
Godeps/_workspace/src/golang.org/x/net/html/charset/testdata/meta-charset-attribute.html
generated
vendored
48
Godeps/_workspace/src/golang.org/x/net/html/charset/testdata/meta-charset-attribute.html
generated
vendored
|
@ -1,48 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en" >
|
|
||||||
<head>
|
|
||||||
<meta charset="iso-8859-15"> <title>meta charset attribute</title>
|
|
||||||
<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'>
|
|
||||||
<link rel='help' href='http://www.w3.org/TR/html5/syntax.html#the-input-byte-stream'>
|
|
||||||
<link rel="stylesheet" type="text/css" href="./generatedtests.css">
|
|
||||||
<script src="http://w3c-test.org/resources/testharness.js"></script>
|
|
||||||
<script src="http://w3c-test.org/resources/testharnessreport.js"></script>
|
|
||||||
<meta name='flags' content='http'>
|
|
||||||
<meta name="assert" content="The character encoding of the page can be set by a meta element with charset attribute.">
|
|
||||||
<style type='text/css'>
|
|
||||||
.test div { width: 50px; }</style>
|
|
||||||
<link rel="stylesheet" type="text/css" href="the-input-byte-stream/support/encodingtests-15.css">
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<p class='title'>meta charset attribute</p>
|
|
||||||
|
|
||||||
|
|
||||||
<div id='log'></div>
|
|
||||||
|
|
||||||
|
|
||||||
<div class='test'><div id='box' class='ýäè'> </div></div>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div class='description'>
|
|
||||||
<p class="assertion" title="Assertion">The character encoding of the page can be set by a meta element with charset attribute.</p>
|
|
||||||
<div class="notes"><p><p>The only character encoding declaration for this HTML file is in the charset attribute of the meta element, which declares the encoding to be ISO 8859-15.</p><p>The test contains a div with a class name that contains the following sequence of bytes: 0xC3 0xBD 0xC3 0xA4 0xC3 0xA8. These represent different sequences of characters in ISO 8859-15, ISO 8859-1 and UTF-8. The external, UTF-8-encoded stylesheet contains a selector <code>.test div.ÜÀÚ</code>. This matches the sequence of bytes above when they are interpreted as ISO 8859-15. If the class name matches the selector then the test will pass.</p></p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="nexttest"><div><a href="generate?test=the-input-byte-stream-015">Next test</a></div><div class="doctype">HTML5</div>
|
|
||||||
<p class="jump">the-input-byte-stream-009<br /><a href="/International/tests/html5/the-input-byte-stream/results-basics#basics" target="_blank">Result summary & related tests</a><br /><a href="http://w3c-test.org/framework/details/i18n-html5/the-input-byte-stream-009" target="_blank">Detailed results for this test</a><br/> <a href="http://www.w3.org/TR/html5/syntax.html#the-input-byte-stream" target="_blank">Link to spec</a></p>
|
|
||||||
<div class='prereq'>Assumptions: <ul><li>The default encoding for the browser you are testing is not set to ISO 8859-15.</li>
|
|
||||||
<li>The test is read from a server that supports HTTP.</li></ul></div>
|
|
||||||
</div>
|
|
||||||
<script>
|
|
||||||
test(function() {
|
|
||||||
assert_equals(document.getElementById('box').offsetWidth, 100);
|
|
||||||
}, " ");
|
|
||||||
</script>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
|
|
||||||
|
|
48
Godeps/_workspace/src/golang.org/x/net/html/charset/testdata/meta-content-attribute.html
generated
vendored
48
Godeps/_workspace/src/golang.org/x/net/html/charset/testdata/meta-content-attribute.html
generated
vendored
|
@ -1,48 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en" >
|
|
||||||
<head>
|
|
||||||
<meta http-equiv="content-type" content="text/html; charset=iso-8859-15"> <title>meta content attribute</title>
|
|
||||||
<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'>
|
|
||||||
<link rel='help' href='http://www.w3.org/TR/html5/syntax.html#the-input-byte-stream'>
|
|
||||||
<link rel="stylesheet" type="text/css" href="./generatedtests.css">
|
|
||||||
<script src="http://w3c-test.org/resources/testharness.js"></script>
|
|
||||||
<script src="http://w3c-test.org/resources/testharnessreport.js"></script>
|
|
||||||
<meta name='flags' content='http'>
|
|
||||||
<meta name="assert" content="The character encoding of the page can be set by a meta element with http-equiv and content attributes.">
|
|
||||||
<style type='text/css'>
|
|
||||||
.test div { width: 50px; }</style>
|
|
||||||
<link rel="stylesheet" type="text/css" href="the-input-byte-stream/support/encodingtests-15.css">
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<p class='title'>meta content attribute</p>
|
|
||||||
|
|
||||||
|
|
||||||
<div id='log'></div>
|
|
||||||
|
|
||||||
|
|
||||||
<div class='test'><div id='box' class='ýäè'> </div></div>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div class='description'>
|
|
||||||
<p class="assertion" title="Assertion">The character encoding of the page can be set by a meta element with http-equiv and content attributes.</p>
|
|
||||||
<div class="notes"><p><p>The only character encoding declaration for this HTML file is in the content attribute of the meta element, which declares the encoding to be ISO 8859-15.</p><p>The test contains a div with a class name that contains the following sequence of bytes: 0xC3 0xBD 0xC3 0xA4 0xC3 0xA8. These represent different sequences of characters in ISO 8859-15, ISO 8859-1 and UTF-8. The external, UTF-8-encoded stylesheet contains a selector <code>.test div.ÜÀÚ</code>. This matches the sequence of bytes above when they are interpreted as ISO 8859-15. If the class name matches the selector then the test will pass.</p></p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="nexttest"><div><a href="generate?test=the-input-byte-stream-009">Next test</a></div><div class="doctype">HTML5</div>
|
|
||||||
<p class="jump">the-input-byte-stream-007<br /><a href="/International/tests/html5/the-input-byte-stream/results-basics#basics" target="_blank">Result summary & related tests</a><br /><a href="http://w3c-test.org/framework/details/i18n-html5/the-input-byte-stream-007" target="_blank">Detailed results for this test</a><br/> <a href="http://www.w3.org/TR/html5/syntax.html#the-input-byte-stream" target="_blank">Link to spec</a></p>
|
|
||||||
<div class='prereq'>Assumptions: <ul><li>The default encoding for the browser you are testing is not set to ISO 8859-15.</li>
|
|
||||||
<li>The test is read from a server that supports HTTP.</li></ul></div>
|
|
||||||
</div>
|
|
||||||
<script>
|
|
||||||
test(function() {
|
|
||||||
assert_equals(document.getElementById('box').offsetWidth, 100);
|
|
||||||
}, " ");
|
|
||||||
</script>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
|
|
||||||
|
|
29
Godeps/_workspace/src/golang.org/x/net/html/entity_test.go
generated
vendored
29
Godeps/_workspace/src/golang.org/x/net/html/entity_test.go
generated
vendored
|
@ -1,29 +0,0 @@
|
||||||
// Copyright 2010 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.
|
|
||||||
|
|
||||||
package html
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
"unicode/utf8"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestEntityLength(t *testing.T) {
|
|
||||||
// We verify that the length of UTF-8 encoding of each value is <= 1 + len(key).
|
|
||||||
// The +1 comes from the leading "&". This property implies that the length of
|
|
||||||
// unescaped text is <= the length of escaped text.
|
|
||||||
for k, v := range entity {
|
|
||||||
if 1+len(k) < utf8.RuneLen(v) {
|
|
||||||
t.Error("escaped entity &" + k + " is shorter than its UTF-8 encoding " + string(v))
|
|
||||||
}
|
|
||||||
if len(k) > longestEntityWithoutSemicolon && k[len(k)-1] != ';' {
|
|
||||||
t.Errorf("entity name %s is %d characters, but longestEntityWithoutSemicolon=%d", k, len(k), longestEntityWithoutSemicolon)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for k, v := range entity2 {
|
|
||||||
if 1+len(k) < utf8.RuneLen(v[0])+utf8.RuneLen(v[1]) {
|
|
||||||
t.Error("escaped entity &" + k + " is shorter than its UTF-8 encoding " + string(v[0]) + string(v[1]))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
Some files were not shown because too many files have changed in this diff Show more
Reference in a new issue