...

Source file src/github.com/go-kivik/kivik/v4/mockdb/clientmock.go

Documentation: github.com/go-kivik/kivik/v4/mockdb

     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  }
   235  

View as plain text