github.com/go-kivik/kivik/v4@v4.3.2/mockdb/clientmock.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 mockdb 14 15 import ( 16 "encoding/json" 17 "fmt" 18 "reflect" 19 "time" 20 21 kivik "github.com/go-kivik/kivik/v4" 22 ) 23 24 // Client allows configuring the mock kivik client. 25 type Client struct { 26 ordered bool 27 dsn string 28 opened int 29 drv *mockDriver 30 expected []expectation 31 newdbcount int 32 } 33 34 // nextExpectation accepts the expected value actual, checks that this is a 35 // valid expectation, and if so, populates actual with the matching expectation. 36 // If the expectation is not expected, an error is returned. 37 func (c *Client) nextExpectation(actual expectation) error { 38 c.drv.Lock() 39 defer c.drv.Unlock() 40 41 var expected expectation 42 var fulfilled int 43 for _, next := range c.expected { 44 next.Lock() 45 if next.fulfilled() { 46 next.Unlock() 47 fulfilled++ 48 continue 49 } 50 51 if c.ordered { 52 if reflect.TypeOf(actual).Elem().Name() == reflect.TypeOf(next).Elem().Name() { 53 if meets(actual, next) { 54 expected = next 55 break 56 } 57 next.Unlock() 58 return fmt.Errorf("Expectation not met:\nExpected: %s\n Actual: %s", 59 next, actual) 60 } 61 next.Unlock() 62 return fmt.Errorf("call to %s was not expected. Next expectation is: %s", actual.method(false), next.method(false)) 63 } 64 if meets(actual, next) { 65 expected = next 66 break 67 } 68 69 next.Unlock() 70 } 71 72 if expected == nil { 73 if fulfilled == len(c.expected) { 74 return fmt.Errorf("call to %s was not expected, all expectations already fulfilled", actual.method(false)) 75 } 76 return fmt.Errorf("call to %s was not expected", actual.method(!c.ordered)) 77 } 78 79 defer expected.Unlock() 80 expected.fulfill() 81 82 reflect.ValueOf(actual).Elem().Set(reflect.ValueOf(expected).Elem()) 83 return nil 84 } 85 86 func (c *Client) open() (*kivik.Client, *Client, error) { 87 client, err := kivik.New("mock", c.dsn) 88 return client, c, err 89 } 90 91 // ExpectationsWereMet returns an error if any outstanding expectations were 92 // not met. 93 func (c *Client) ExpectationsWereMet() error { 94 c.drv.Lock() 95 defer c.drv.Unlock() 96 for _, e := range c.expected { 97 e.Lock() 98 fulfilled := e.fulfilled() 99 e.Unlock() 100 101 if !fulfilled { 102 return fmt.Errorf("there is a remaining unmet expectation: %s", e) 103 } 104 } 105 return nil 106 } 107 108 // MatchExpectationsInOrder sets whether expectations should occur in the 109 // precise order in which they were defined. 110 func (c *Client) MatchExpectationsInOrder(b bool) { 111 c.ordered = b 112 } 113 114 // ExpectCreateDB queues an expectation for a CreateDB() call. 115 func (c *Client) ExpectCreateDB() *ExpectedCreateDB { 116 e := &ExpectedCreateDB{} 117 c.expected = append(c.expected, e) 118 return e 119 } 120 121 // NewDB creates a new mock DB object, which can be used along with ExpectDB() 122 // or ExpectCreateDB() calls to mock database actions. 123 func (c *Client) NewDB() *DB { 124 c.newdbcount++ 125 return &DB{ 126 client: c, 127 id: c.newdbcount, 128 } 129 } 130 131 // NewRows returns a new, empty set of rows, which can be returned by any of 132 // the row-returning expectations. 133 func NewRows() *Rows { 134 return &Rows{} 135 } 136 137 // NewChanges returns a new, empty changes set, which can be returned by the 138 // DB.Changes() expectation. 139 func NewChanges() *Changes { 140 return &Changes{} 141 } 142 143 // NewDBUpdates returns a new, empty update set, which can be returned by the 144 // DBUpdates() expectation. 145 func NewDBUpdates() *Updates { 146 return &Updates{} 147 } 148 149 // Replication is a replication instance. 150 type Replication struct { 151 id string 152 source string 153 target string 154 startTime time.Time 155 endTime time.Time 156 state string 157 err error 158 } 159 160 // NewReplication returns a new, empty Replication. 161 func (c *Client) NewReplication() *Replication { 162 return &Replication{} 163 } 164 165 // MarshalJSON satisfies the json.Marshaler interface. 166 func (r *Replication) MarshalJSON() ([]byte, error) { 167 type rep struct { 168 ID string `json:"replication_id,omitempty"` 169 Source string `json:"source,omitempty"` 170 Target string `json:"target,omitempty"` 171 StartTime *time.Time `json:"start_time,omitempty"` 172 EndTime *time.Time `json:"end_time,omitempty"` 173 State string `json:"state,omitempty"` 174 Err string `json:"error,omitempty"` 175 } 176 doc := &rep{ 177 ID: r.id, 178 Source: r.source, 179 Target: r.target, 180 State: r.state, 181 } 182 if !r.startTime.IsZero() { 183 doc.StartTime = &r.startTime 184 } 185 if !r.endTime.IsZero() { 186 doc.EndTime = &r.endTime 187 } 188 if r.err != nil { 189 doc.Err = r.err.Error() 190 } 191 return json.Marshal(doc) 192 } 193 194 // ID sets the replication ID. 195 func (r *Replication) ID(id string) *Replication { 196 r.id = id 197 return r 198 } 199 200 // Source sets the replication source. 201 func (r *Replication) Source(s string) *Replication { 202 r.source = s 203 return r 204 } 205 206 // Target sets the replication target. 207 func (r *Replication) Target(t string) *Replication { 208 r.target = t 209 return r 210 } 211 212 // StartTime sets the replication start time. 213 func (r *Replication) StartTime(t time.Time) *Replication { 214 r.startTime = t 215 return r 216 } 217 218 // EndTime sets the replication end time. 219 func (r *Replication) EndTime(t time.Time) *Replication { 220 r.endTime = t 221 return r 222 } 223 224 // State sets the replication state. 225 func (r *Replication) State(s kivik.ReplicationState) *Replication { 226 r.state = string(s) 227 return r 228 } 229 230 // Err sets the replication error. 231 func (r *Replication) Err(e error) *Replication { 232 r.err = e 233 return r 234 }