github.com/go-kivik/kivik/v4@v4.3.2/couchdb/mock_test.go (about) 1 // Licensed under the Apache License, Version 2.0 (the "License"); you may not 2 // use this file except in compliance with the License. You may obtain a copy of 3 // the License at 4 // 5 // http://www.apache.org/licenses/LICENSE-2.0 6 // 7 // Unless required by applicable law or agreed to in writing, software 8 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 9 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 10 // License for the specific language governing permissions and limitations under 11 // the License. 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 // consume consumes and closes r or does nothing if it is nil. 94 func consume(r io.ReadCloser) error { 95 if r == nil { 96 return nil 97 } 98 defer r.Close() // nolint: errcheck 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 }