...
1
2
3
4
5
6
7
8
9
10
11
12
13 package couchdb
14
15 import (
16 "context"
17 "errors"
18 "io"
19 "net/http"
20 "net/url"
21 "runtime"
22 "strings"
23 "testing"
24 "time"
25
26 "github.com/go-kivik/kivik/v4/couchdb/chttp"
27 "github.com/go-kivik/kivik/v4/int/mock"
28 "github.com/go-kivik/kivik/v4/kiviktest/kt"
29 )
30
31 const isGopherJS = runtime.GOOS == "js" || runtime.GOARCH == "js"
32
33 type customTransport func(*http.Request) (*http.Response, error)
34
35 var _ http.RoundTripper = customTransport(nil)
36
37 func (t customTransport) RoundTrip(req *http.Request) (*http.Response, error) {
38 return t(req)
39 }
40
41 func newTestDB(response *http.Response, err error) *db {
42 return &db{
43 dbName: "testdb",
44 client: newTestClient(response, err),
45 }
46 }
47
48 func newCustomDB(fn func(*http.Request) (*http.Response, error)) *db {
49 return &db{
50 dbName: "testdb",
51 client: newCustomClient(fn),
52 }
53 }
54
55 func newTestClient(response *http.Response, err error) *client {
56 return newCustomClient(func(req *http.Request) (*http.Response, error) {
57 if e := consume(req.Body); e != nil {
58 return nil, e
59 }
60 if err != nil {
61 return nil, err
62 }
63 response := response
64 response.Request = req
65 return response, nil
66 })
67 }
68
69 func newCustomClient(fn func(*http.Request) (*http.Response, error)) *client {
70 chttpClient, _ := chttp.New(&http.Client{}, "http://example.com/", OptionNoRequestCompression())
71 chttpClient.Client.Transport = customTransport(fn)
72 return &client{
73 Client: chttpClient,
74 }
75 }
76
77 func Body(str string) io.ReadCloser {
78 if !strings.HasSuffix(str, "\n") {
79 str += "\n"
80 }
81 return io.NopCloser(strings.NewReader(str))
82 }
83
84 func parseTime(t *testing.T, str string) time.Time {
85 t.Helper()
86 ts, err := time.Parse(time.RFC3339, str)
87 if err != nil {
88 t.Fatal(err)
89 }
90 return ts
91 }
92
93
94 func consume(r io.ReadCloser) error {
95 if r == nil {
96 return nil
97 }
98 defer r.Close()
99 _, e := io.ReadAll(r)
100 return e
101 }
102
103 type mockReadCloser struct {
104 ReadFunc func([]byte) (int, error)
105 CloseFunc func() error
106 }
107
108 var _ io.ReadCloser = &mockReadCloser{}
109
110 func (rc *mockReadCloser) Read(p []byte) (int, error) {
111 return rc.ReadFunc(p)
112 }
113
114 func (rc *mockReadCloser) Close() error {
115 return rc.CloseFunc()
116 }
117
118 func realDB(t *testing.T) *db {
119 t.Helper()
120 if isGopherJS {
121 t.Skip("Network tests skipped for GopherJS")
122 }
123 db, err := realDBConnect(t)
124 if err != nil {
125 if errors.Is(err, &url.Error{}) {
126 t.Skip("Cannot connect to CouchDB")
127 }
128 if strings.HasSuffix(err.Error(), "connect: connection refused") {
129 t.Skip("Cannot connect to CouchDB")
130 }
131 t.Fatal(err)
132 }
133 return db
134 }
135
136 func realDBConnect(t *testing.T) (*db, error) {
137 t.Helper()
138 driver := &couch{}
139 c, err := driver.NewClient(kt.DSN3(t), OptionNoRequestCompression())
140 if err != nil {
141 return nil, err
142 }
143 dbname := kt.TestDBName(t)
144
145 err = c.CreateDB(context.Background(), dbname, mock.NilOption)
146 return &db{
147 client: c.(*client),
148 dbName: dbname,
149 }, err
150 }
151
View as plain text