...

Source file src/github.com/go-kivik/kivik/v4/mockdb/client_test.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  	"context"
    17  	"errors"
    18  	"fmt"
    19  	"testing"
    20  	"time"
    21  
    22  	"gitlab.com/flimzy/testy"
    23  
    24  	"github.com/go-kivik/kivik/v4"
    25  	"github.com/go-kivik/kivik/v4/driver"
    26  )
    27  
    28  type mockTest struct {
    29  	setup func(*Client)
    30  	test  func(*testing.T, *kivik.Client)
    31  	err   string
    32  }
    33  
    34  func testMock(t *testing.T, test mockTest) {
    35  	t.Helper()
    36  	client, mock, err := New()
    37  	if err != nil {
    38  		t.Fatalf("error creating mock database: %s", err)
    39  	}
    40  	t.Cleanup(func() {
    41  		_ = client.Close()
    42  	})
    43  	if test.setup != nil {
    44  		test.setup(mock)
    45  	}
    46  	if test.test != nil {
    47  		test.test(t, client)
    48  	}
    49  	err = mock.ExpectationsWereMet()
    50  	if !testy.ErrorMatchesRE(test.err, err) {
    51  		t.Errorf("ExpectationsWereMet returned unexpected error: %s", err)
    52  	}
    53  }
    54  
    55  func TestCloseClient(t *testing.T) {
    56  	tests := testy.NewTable()
    57  	tests.Add("err", mockTest{
    58  		setup: func(m *Client) {
    59  			m.ExpectClose().WillReturnError(errors.New("close failed"))
    60  		},
    61  		test: func(t *testing.T, c *kivik.Client) { //nolint:thelper // not a helper
    62  			err := c.Close()
    63  			if !testy.ErrorMatches("close failed", err) {
    64  				t.Errorf("unexpected error: %s", err)
    65  			}
    66  		},
    67  		err: "",
    68  	})
    69  	tests.Add("unexpected", mockTest{
    70  		test: func(t *testing.T, c *kivik.Client) { //nolint:thelper // not a helper
    71  			err := c.Close()
    72  			const want = "call to Close() was not expected, all expectations already fulfilled"
    73  			if !testy.ErrorMatches(want, err) {
    74  				t.Errorf("unexpected error: %s", err)
    75  			}
    76  		},
    77  	})
    78  	tests.Add("callback", mockTest{
    79  		setup: func(m *Client) {
    80  			m.ExpectClose().WillExecute(func() error {
    81  				return errors.New("custom error")
    82  			})
    83  		},
    84  		test: func(t *testing.T, c *kivik.Client) { //nolint:thelper // Not a helper
    85  			err := c.Close()
    86  			if !testy.ErrorMatches("custom error", err) {
    87  				t.Errorf("Unexpected error: %s", err)
    88  			}
    89  		},
    90  	})
    91  	tests.Run(t, testMock)
    92  }
    93  
    94  func TestAllDBs(t *testing.T) {
    95  	tests := testy.NewTable()
    96  	tests.Add("error", mockTest{
    97  		setup: func(m *Client) {
    98  			m.ExpectAllDBs().WillReturnError(fmt.Errorf("AllDBs failed"))
    99  		},
   100  		test: func(t *testing.T, c *kivik.Client) { //nolint:thelper // Not a helper
   101  			_, err := c.AllDBs(context.TODO())
   102  			if !testy.ErrorMatches("AllDBs failed", err) {
   103  				t.Errorf("unexpected error: %s", err)
   104  			}
   105  		},
   106  	})
   107  	tests.Add("unexpected", mockTest{
   108  		test: func(t *testing.T, c *kivik.Client) { //nolint:thelper // Not a helper
   109  			_, err := c.AllDBs(context.TODO())
   110  			if !testy.ErrorMatches("call to AllDBs() was not expected, all expectations already fulfilled", err) {
   111  				t.Errorf("Unexpected error: %s", err)
   112  			}
   113  		},
   114  	})
   115  	tests.Add("success", func() interface{} {
   116  		expected := []string{"a", "b", "c"}
   117  		return mockTest{
   118  			setup: func(m *Client) {
   119  				m.ExpectAllDBs().WillReturn(expected)
   120  			},
   121  			test: func(t *testing.T, c *kivik.Client) { //nolint:thelper // Not a helper
   122  				result, err := c.AllDBs(context.TODO())
   123  				if !testy.ErrorMatches("", err) {
   124  					t.Errorf("Unexpected error: %s", err)
   125  				}
   126  				if d := testy.DiffInterface(expected, result); d != nil {
   127  					t.Error(d)
   128  				}
   129  			},
   130  		}
   131  	})
   132  	tests.Add("delay", mockTest{
   133  		setup: func(m *Client) {
   134  			m.ExpectAllDBs().WillDelay(time.Second)
   135  		},
   136  		test: func(t *testing.T, c *kivik.Client) { //nolint:thelper // Not a helper
   137  			_, err := c.AllDBs(newCanceledContext())
   138  			if !testy.ErrorMatches("context canceled", err) {
   139  				t.Errorf("Unexpected error: %s", err)
   140  			}
   141  		},
   142  	})
   143  	tests.Add("options", mockTest{
   144  		setup: func(m *Client) {
   145  			m.ExpectAllDBs().WithOptions(kivik.Param("foo", 123))
   146  		},
   147  		test: func(t *testing.T, c *kivik.Client) { //nolint:thelper // Not a helper
   148  			_, err := c.AllDBs(context.TODO(), kivik.Param("foo", 123))
   149  			if !testy.ErrorMatches("", err) {
   150  				t.Errorf("Unexpected error: %s", err)
   151  			}
   152  		},
   153  	})
   154  	tests.Add("callback", mockTest{
   155  		setup: func(m *Client) {
   156  			m.ExpectAllDBs().WillExecute(func(context.Context, driver.Options) ([]string, error) {
   157  				return nil, errors.New("custom error")
   158  			})
   159  		},
   160  		test: func(t *testing.T, c *kivik.Client) { //nolint:thelper // Not a helper
   161  			_, err := c.AllDBs(context.TODO())
   162  			if !testy.ErrorMatches("custom error", err) {
   163  				t.Errorf("Unexpected error: %s", err)
   164  			}
   165  		},
   166  	})
   167  	tests.Run(t, testMock)
   168  }
   169  
   170  func TestClusterSetup(t *testing.T) {
   171  	tests := testy.NewTable()
   172  	tests.Add("error", mockTest{
   173  		setup: func(m *Client) {
   174  			m.ExpectClusterSetup().WillReturnError(errors.New("setup error"))
   175  		},
   176  		test: func(t *testing.T, c *kivik.Client) { //nolint:thelper // Not a helper
   177  			err := c.ClusterSetup(context.TODO(), 123)
   178  			if !testy.ErrorMatches("setup error", err) {
   179  				t.Errorf("Unexpected error: %s", err)
   180  			}
   181  		},
   182  	})
   183  	tests.Add("action", mockTest{
   184  		setup: func(m *Client) {
   185  			m.ExpectClusterSetup().WithAction(123)
   186  		},
   187  		test: func(t *testing.T, c *kivik.Client) { //nolint:thelper // Not a helper
   188  			err := c.ClusterSetup(context.TODO(), 123)
   189  			if !testy.ErrorMatches("", err) {
   190  				t.Errorf("Unexpected error: %s", err)
   191  			}
   192  		},
   193  	})
   194  	tests.Add("delay", mockTest{
   195  		setup: func(m *Client) {
   196  			m.ExpectClusterSetup().WillDelay(time.Second)
   197  		},
   198  		test: func(t *testing.T, c *kivik.Client) { //nolint:thelper // Not a helper
   199  			err := c.ClusterSetup(newCanceledContext(), 123)
   200  			if !testy.ErrorMatches("context canceled", err) {
   201  				t.Errorf("Unexpected error: %s", err)
   202  			}
   203  		},
   204  	})
   205  	tests.Add("unexpected", mockTest{
   206  		test: func(t *testing.T, c *kivik.Client) { //nolint:thelper // Not a helper
   207  			err := c.ClusterSetup(context.TODO(), 123)
   208  			if !testy.ErrorMatches("call to ClusterSetup() was not expected, all expectations already fulfilled", err) {
   209  				t.Errorf("Unexpected error: %s", err)
   210  			}
   211  		},
   212  	})
   213  	tests.Add("callback", mockTest{
   214  		setup: func(m *Client) {
   215  			m.ExpectClusterSetup().WillExecute(func(context.Context, interface{}) error {
   216  				return errors.New("custom error")
   217  			})
   218  		},
   219  		test: func(t *testing.T, c *kivik.Client) { //nolint:thelper // Not a helper
   220  			err := c.ClusterSetup(context.TODO(), 123)
   221  			if !testy.ErrorMatches("custom error", err) {
   222  				t.Errorf("Unexpected error: %s", err)
   223  			}
   224  		},
   225  	})
   226  	tests.Run(t, testMock)
   227  }
   228  
   229  func TestClusterStatus(t *testing.T) {
   230  	tests := testy.NewTable()
   231  	tests.Add("error", mockTest{
   232  		setup: func(m *Client) {
   233  			m.ExpectClusterStatus().WillReturnError(errors.New("status error"))
   234  		},
   235  		test: func(t *testing.T, c *kivik.Client) { //nolint:thelper // Not a helper
   236  			_, err := c.ClusterStatus(context.TODO())
   237  			if !testy.ErrorMatches("status error", err) {
   238  				t.Errorf("Unexpected error: %s", err)
   239  			}
   240  		},
   241  	})
   242  	tests.Add("options", mockTest{
   243  		setup: func(m *Client) {
   244  			m.ExpectClusterStatus().WithOptions(kivik.Param("foo", 123))
   245  		},
   246  		test: func(t *testing.T, c *kivik.Client) { //nolint:thelper // Not a helper
   247  			_, err := c.ClusterStatus(context.TODO())
   248  			if !testy.ErrorMatchesRE(`map\[foo:123]`, err) {
   249  				t.Errorf("Unexpected error: %s", err)
   250  			}
   251  		},
   252  		err: "there is a remaining unmet expectation",
   253  	})
   254  	tests.Add("success", func() interface{} {
   255  		const expected = "oink"
   256  		return mockTest{
   257  			setup: func(m *Client) {
   258  				m.ExpectClusterStatus().WillReturn(expected)
   259  			},
   260  			test: func(t *testing.T, c *kivik.Client) { //nolint:thelper // Not a helper
   261  				result, err := c.ClusterStatus(context.TODO())
   262  				if !testy.ErrorMatches("", err) {
   263  					t.Errorf("Unexpected error: %s", err)
   264  				}
   265  				if result != expected {
   266  					t.Errorf("Unexpected result: %s", result)
   267  				}
   268  			},
   269  		}
   270  	})
   271  	tests.Add("delay", mockTest{
   272  		setup: func(m *Client) {
   273  			m.ExpectClusterStatus().WillDelay(time.Second)
   274  		},
   275  		test: func(t *testing.T, c *kivik.Client) { //nolint:thelper // Not a helper
   276  			_, err := c.ClusterStatus(newCanceledContext())
   277  			if !testy.ErrorMatches("context canceled", err) {
   278  				t.Errorf("Unexpected error: %s", err)
   279  			}
   280  		},
   281  	})
   282  	tests.Add("unordered", mockTest{
   283  		setup: func(m *Client) {
   284  			m.ExpectClose()
   285  			m.ExpectClusterStatus()
   286  			m.MatchExpectationsInOrder(false)
   287  		},
   288  		test: func(t *testing.T, c *kivik.Client) { //nolint:thelper // Not a helper
   289  			_, err := c.ClusterStatus(context.TODO())
   290  			if !testy.ErrorMatches("", err) {
   291  				t.Errorf("Unexpected error: %s", err)
   292  			}
   293  		},
   294  		err: "there is a remaining unmet expectation: call to Close()",
   295  	})
   296  	tests.Add("unexpected", mockTest{
   297  		setup: func(m *Client) {
   298  			m.ExpectClose()
   299  			m.MatchExpectationsInOrder(false)
   300  		},
   301  		test: func(t *testing.T, c *kivik.Client) { //nolint:thelper // Not a helper
   302  			_, err := c.ClusterStatus(context.TODO())
   303  			if !testy.ErrorMatches("call to ClusterStatus(ctx, [?]) was not expected", err) {
   304  				t.Errorf("Unexpected error: %s", err)
   305  			}
   306  		},
   307  		err: "there is a remaining unmet expectation: call to Close()",
   308  	})
   309  	tests.Add("callback", mockTest{
   310  		setup: func(m *Client) {
   311  			m.ExpectClusterStatus().WillExecute(func(context.Context, driver.Options) (string, error) {
   312  				return "", errors.New("custom error")
   313  			})
   314  		},
   315  		test: func(t *testing.T, c *kivik.Client) { //nolint:thelper // Not a helper
   316  			_, err := c.ClusterStatus(newCanceledContext())
   317  			if !testy.ErrorMatches("custom error", err) {
   318  				t.Errorf("Unexpected error: %s", err)
   319  			}
   320  		},
   321  	})
   322  	tests.Run(t, testMock)
   323  }
   324  
   325  func TestDBExists(t *testing.T) {
   326  	tests := testy.NewTable()
   327  	tests.Add("error", mockTest{
   328  		setup: func(m *Client) {
   329  			m.ExpectDBExists().WillReturnError(errors.New("existence error"))
   330  		},
   331  		test: func(t *testing.T, c *kivik.Client) { //nolint:thelper // Not a helper
   332  			_, err := c.DBExists(context.TODO(), "foo")
   333  			if !testy.ErrorMatches("existence error", err) {
   334  				t.Errorf("Unexpected error: %s", err)
   335  			}
   336  		},
   337  	})
   338  	tests.Add("name", mockTest{
   339  		setup: func(m *Client) {
   340  			m.ExpectDBExists().WithName("foo")
   341  		},
   342  		test: func(t *testing.T, c *kivik.Client) { //nolint:thelper // Not a helper
   343  			exists, err := c.DBExists(context.TODO(), "foo")
   344  			if !testy.ErrorMatches("", err) {
   345  				t.Errorf("Unexpected error: %s", err)
   346  			}
   347  			if exists {
   348  				t.Errorf("DB shouldn't exist")
   349  			}
   350  		},
   351  	})
   352  	tests.Add("options", mockTest{
   353  		setup: func(m *Client) {
   354  			m.ExpectDBExists().WithOptions(kivik.Param("foo", 123))
   355  		},
   356  		test: func(t *testing.T, c *kivik.Client) { //nolint:thelper // Not a helper
   357  			_, err := c.DBExists(context.TODO(), "foo")
   358  			if !testy.ErrorMatchesRE(`map\[foo:123]`, err) {
   359  				t.Errorf("Unexpected error: %s", err)
   360  			}
   361  		},
   362  		err: "there is a remaining unmet expectation",
   363  	})
   364  	tests.Add("exists", mockTest{
   365  		setup: func(m *Client) {
   366  			m.ExpectDBExists().WillReturn(true)
   367  		},
   368  		test: func(t *testing.T, c *kivik.Client) { //nolint:thelper // Not a helper
   369  			exists, err := c.DBExists(context.TODO(), "foo")
   370  			if !testy.ErrorMatchesRE("", err) {
   371  				t.Errorf("Unexpected error: %s", err)
   372  			}
   373  			if !exists {
   374  				t.Errorf("DB should exist")
   375  			}
   376  		},
   377  	})
   378  	tests.Add("delay", mockTest{
   379  		setup: func(m *Client) {
   380  			m.ExpectDBExists().WillDelay(time.Second)
   381  		},
   382  		test: func(t *testing.T, c *kivik.Client) { //nolint:thelper // Not a helper
   383  			_, err := c.DBExists(newCanceledContext(), "foo")
   384  			if !testy.ErrorMatches("context canceled", err) {
   385  				t.Errorf("Unexpected error: %s", err)
   386  			}
   387  		},
   388  	})
   389  	tests.Run(t, testMock)
   390  }
   391  
   392  func TestDestroyDB(t *testing.T) {
   393  	tests := testy.NewTable()
   394  	tests.Add("error", mockTest{
   395  		setup: func(m *Client) {
   396  			m.ExpectDestroyDB().WillReturnError(errors.New("foo err"))
   397  		},
   398  		test: func(t *testing.T, c *kivik.Client) { //nolint:thelper // Not a helper
   399  			err := c.DestroyDB(newCanceledContext(), "foo")
   400  			if !testy.ErrorMatches("foo err", err) {
   401  				t.Errorf("Unexpected error: %s", err)
   402  			}
   403  		},
   404  	})
   405  	tests.Add("name", mockTest{
   406  		setup: func(m *Client) {
   407  			m.ExpectDestroyDB().WithName("foo")
   408  		},
   409  		test: func(t *testing.T, c *kivik.Client) { //nolint:thelper // Not a helper
   410  			err := c.DestroyDB(newCanceledContext(), "foo")
   411  			if !testy.ErrorMatches("", err) {
   412  				t.Errorf("Unexpected error: %s", err)
   413  			}
   414  		},
   415  	})
   416  	tests.Add("options", mockTest{
   417  		setup: func(m *Client) {
   418  			m.ExpectDestroyDB().WithOptions(kivik.Param("foo", 123))
   419  		},
   420  		test: func(t *testing.T, c *kivik.Client) { //nolint:thelper // Not a helper
   421  			err := c.DestroyDB(newCanceledContext(), "foo")
   422  			if !testy.ErrorMatchesRE(`map\[foo:123]`, err) {
   423  				t.Errorf("Unexpected error: %s", err)
   424  			}
   425  		},
   426  		err: "there is a remaining unmet expectation",
   427  	})
   428  	tests.Add("delay", mockTest{
   429  		setup: func(m *Client) {
   430  			m.ExpectDestroyDB().WillDelay(time.Second)
   431  		},
   432  		test: func(t *testing.T, c *kivik.Client) { //nolint:thelper // Not a helper
   433  			err := c.DestroyDB(newCanceledContext(), "foo")
   434  			if !testy.ErrorMatches("context canceled", err) {
   435  				t.Errorf("Unexpected error: %s", err)
   436  			}
   437  		},
   438  	})
   439  	tests.Run(t, testMock)
   440  }
   441  
   442  func TestDBsStats(t *testing.T) {
   443  	tests := testy.NewTable()
   444  	tests.Add("error", mockTest{
   445  		setup: func(m *Client) {
   446  			m.ExpectDBsStats().WillReturnError(errors.New("stats error"))
   447  		},
   448  		test: func(t *testing.T, c *kivik.Client) { //nolint:thelper // Not a helper
   449  			_, err := c.DBsStats(context.TODO(), []string{"foo"})
   450  			if !testy.ErrorMatches("stats error", err) {
   451  				t.Errorf("Unexpected error: %s", err)
   452  			}
   453  		},
   454  	})
   455  	tests.Add("names", mockTest{
   456  		setup: func(m *Client) {
   457  			m.ExpectDBsStats().WithNames([]string{"a", "b"})
   458  		},
   459  		test: func(t *testing.T, c *kivik.Client) { //nolint:thelper // Not a helper
   460  			_, err := c.DBsStats(context.TODO(), []string{"foo"})
   461  			if !testy.ErrorMatchesRE("[a b]", err) {
   462  				t.Errorf("Unexpected error: %s", err)
   463  			}
   464  		},
   465  		err: "there is a remaining unmet expectation",
   466  	})
   467  	tests.Add("success", func() interface{} {
   468  		return mockTest{
   469  			setup: func(m *Client) {
   470  				m.ExpectDBsStats().WillReturn([]*driver.DBStats{
   471  					{Name: "foo", Cluster: &driver.ClusterStats{Replicas: 5}},
   472  					{Name: "bar"},
   473  				})
   474  			},
   475  			test: func(t *testing.T, c *kivik.Client) { //nolint:thelper // Not a helper
   476  				result, err := c.DBsStats(context.TODO(), []string{"foo", "bar"})
   477  				if !testy.ErrorMatchesRE("", err) {
   478  					t.Errorf("Unexpected error: %s", err)
   479  				}
   480  				expected := []*kivik.DBStats{
   481  					{Name: "foo", Cluster: &kivik.ClusterConfig{Replicas: 5}},
   482  					{Name: "bar"},
   483  				}
   484  				if d := testy.DiffInterface(expected, result); d != nil {
   485  					t.Error(d)
   486  				}
   487  			},
   488  		}
   489  	})
   490  	tests.Add("delay", mockTest{
   491  		setup: func(m *Client) {
   492  			m.ExpectDBsStats().WillDelay(time.Second)
   493  		},
   494  		test: func(t *testing.T, c *kivik.Client) { //nolint:thelper // Not a helper
   495  			_, err := c.DBsStats(newCanceledContext(), []string{"foo"})
   496  			if !testy.ErrorMatches("context canceled", err) {
   497  				t.Errorf("Unexpected error: %s", err)
   498  			}
   499  		},
   500  	})
   501  	tests.Run(t, testMock)
   502  }
   503  
   504  func TestPing(t *testing.T) {
   505  	tests := testy.NewTable()
   506  	tests.Add("unreachable", mockTest{
   507  		setup: func(m *Client) {
   508  			m.ExpectPing()
   509  		},
   510  		test: func(t *testing.T, c *kivik.Client) { //nolint:thelper // Not a helper
   511  			reachable, err := c.Ping(context.TODO())
   512  			if !testy.ErrorMatches("", err) {
   513  				t.Errorf("Unexpected error: %s", err)
   514  			}
   515  			if reachable {
   516  				t.Errorf("Expected db to be unreachable")
   517  			}
   518  		},
   519  	})
   520  	tests.Add("reachable", mockTest{
   521  		setup: func(m *Client) {
   522  			m.ExpectPing().WillReturn(true)
   523  		},
   524  		test: func(t *testing.T, c *kivik.Client) { //nolint:thelper // Not a helper
   525  			reachable, err := c.Ping(context.TODO())
   526  			if !testy.ErrorMatches("", err) {
   527  				t.Errorf("Unexpected error: %s", err)
   528  			}
   529  			if !reachable {
   530  				t.Errorf("Expected db to be reachable")
   531  			}
   532  		},
   533  	})
   534  	tests.Add("error", mockTest{
   535  		setup: func(m *Client) {
   536  			m.ExpectPing().WillReturnError(errors.New("foo err"))
   537  		},
   538  		test: func(t *testing.T, c *kivik.Client) { //nolint:thelper // Not a helper
   539  			_, err := c.Ping(context.TODO())
   540  			if !testy.ErrorMatches("foo err", err) {
   541  				t.Errorf("Unexpected error: %s", err)
   542  			}
   543  		},
   544  	})
   545  	tests.Add("unexpected", mockTest{
   546  		test: func(t *testing.T, c *kivik.Client) { //nolint:thelper // Not a helper
   547  			_, err := c.Ping(context.TODO())
   548  			if !testy.ErrorMatches("call to Ping() was not expected, all expectations already fulfilled", err) {
   549  				t.Errorf("Unexpected error: %s", err)
   550  			}
   551  		},
   552  	})
   553  	tests.Add("delay", mockTest{
   554  		setup: func(m *Client) {
   555  			m.ExpectPing().WillDelay(time.Second)
   556  		},
   557  		test: func(t *testing.T, c *kivik.Client) { //nolint:thelper // Not a helper
   558  			_, err := c.Ping(newCanceledContext())
   559  			if !testy.ErrorMatches("context canceled", err) {
   560  				t.Errorf("Unexpected error: %s", err)
   561  			}
   562  		},
   563  	})
   564  	tests.Run(t, testMock)
   565  }
   566  
   567  func TestSession(t *testing.T) {
   568  	tests := testy.NewTable()
   569  	tests.Add("session", func() interface{} {
   570  		return mockTest{
   571  			setup: func(m *Client) {
   572  				m.ExpectSession().WillReturn(&driver.Session{
   573  					Name: "bob",
   574  				})
   575  			},
   576  			test: func(t *testing.T, c *kivik.Client) { //nolint:thelper // Not a helper
   577  				session, err := c.Session(context.TODO())
   578  				if !testy.ErrorMatches("", err) {
   579  					t.Errorf("Unexpected error: %s", err)
   580  				}
   581  				expected := &kivik.Session{
   582  					Name: "bob",
   583  				}
   584  				if d := testy.DiffInterface(expected, session); d != nil {
   585  					t.Error(d)
   586  				}
   587  			},
   588  		}
   589  	})
   590  	tests.Add("unexpected", mockTest{
   591  		test: func(t *testing.T, c *kivik.Client) { //nolint:thelper // Not a helper
   592  			_, err := c.Session(context.TODO())
   593  			if !testy.ErrorMatches("call to Session() was not expected, all expectations already fulfilled", err) {
   594  				t.Errorf("Unexpected error: %s", err)
   595  			}
   596  		},
   597  	})
   598  	tests.Add("error", mockTest{
   599  		setup: func(m *Client) {
   600  			m.ExpectSession().WillReturnError(errors.New("foo err"))
   601  		},
   602  		test: func(t *testing.T, c *kivik.Client) { //nolint:thelper // Not a helper
   603  			_, err := c.Session(context.TODO())
   604  			if !testy.ErrorMatches("foo err", err) {
   605  				t.Errorf("Unexpected error: %s", err)
   606  			}
   607  		},
   608  	})
   609  	tests.Add("delay", mockTest{
   610  		setup: func(m *Client) {
   611  			m.ExpectSession().WillDelay(time.Second)
   612  		},
   613  		test: func(t *testing.T, c *kivik.Client) { //nolint:thelper // Not a helper
   614  			_, err := c.Session(newCanceledContext())
   615  			if !testy.ErrorMatches("context canceled", err) {
   616  				t.Errorf("Unexpected error: %s", err)
   617  			}
   618  		},
   619  	})
   620  	tests.Run(t, testMock)
   621  }
   622  
   623  func TestVersion(t *testing.T) {
   624  	tests := testy.NewTable()
   625  	tests.Add("version", func() interface{} {
   626  		return mockTest{
   627  			setup: func(m *Client) {
   628  				m.ExpectVersion().WillReturn(&driver.Version{Version: "1.2"})
   629  			},
   630  			test: func(t *testing.T, c *kivik.Client) { //nolint:thelper // Not a helper
   631  				session, err := c.Version(context.TODO())
   632  				if !testy.ErrorMatches("", err) {
   633  					t.Errorf("Unexpected error: %s", err)
   634  				}
   635  				expected := &kivik.ServerVersion{Version: "1.2"}
   636  				if d := testy.DiffInterface(expected, session); d != nil {
   637  					t.Error(d)
   638  				}
   639  			},
   640  		}
   641  	})
   642  	tests.Add("unexpected", mockTest{
   643  		test: func(t *testing.T, c *kivik.Client) { //nolint:thelper // Not a helper
   644  			_, err := c.Version(context.TODO())
   645  			if !testy.ErrorMatches("call to Version() was not expected, all expectations already fulfilled", err) {
   646  				t.Errorf("Unexpected error: %s", err)
   647  			}
   648  		},
   649  	})
   650  	tests.Add("error", mockTest{
   651  		setup: func(m *Client) {
   652  			m.ExpectVersion().WillReturnError(errors.New("foo err"))
   653  		},
   654  		test: func(t *testing.T, c *kivik.Client) { //nolint:thelper // Not a helper
   655  			_, err := c.Version(context.TODO())
   656  			if !testy.ErrorMatches("foo err", err) {
   657  				t.Errorf("Unexpected error: %s", err)
   658  			}
   659  		},
   660  	})
   661  	tests.Add("delay", mockTest{
   662  		setup: func(m *Client) {
   663  			m.ExpectVersion().WillDelay(time.Second)
   664  		},
   665  		test: func(t *testing.T, c *kivik.Client) { //nolint:thelper // Not a helper
   666  			_, err := c.Version(newCanceledContext())
   667  			if !testy.ErrorMatches("context canceled", err) {
   668  				t.Errorf("Unexpected error: %s", err)
   669  			}
   670  		},
   671  	})
   672  	tests.Run(t, testMock)
   673  }
   674  
   675  func TestDB(t *testing.T) {
   676  	tests := testy.NewTable()
   677  	tests.Add("name", mockTest{
   678  		setup: func(m *Client) {
   679  			m.ExpectDB().WithName("foo")
   680  		},
   681  		test: func(t *testing.T, c *kivik.Client) { //nolint:thelper // Not a helper
   682  			err := c.DB("foo").Err()
   683  			if !testy.ErrorMatches("", err) {
   684  				t.Errorf("Unexpected error: %s", err)
   685  			}
   686  		},
   687  	})
   688  	tests.Add("unexpected", mockTest{
   689  		test: func(t *testing.T, c *kivik.Client) { //nolint:thelper // Not a helper
   690  			err := c.DB("foo").Err()
   691  			if !testy.ErrorMatches("call to DB() was not expected, all expectations already fulfilled", err) {
   692  				t.Errorf("Unexpected error: %s", err)
   693  			}
   694  		},
   695  	})
   696  	tests.Add("options", mockTest{
   697  		setup: func(m *Client) {
   698  			m.ExpectDB().WithOptions(kivik.Param("foo", 123))
   699  		},
   700  		test: func(t *testing.T, c *kivik.Client) { //nolint:thelper // Not a helper
   701  			err := c.DB("foo", kivik.Param("foo", 123)).Err()
   702  			if !testy.ErrorMatches("", err) {
   703  				t.Errorf("Unexpected error: %s", err)
   704  			}
   705  		},
   706  	})
   707  	tests.Add("success", mockTest{
   708  		setup: func(m *Client) {
   709  			m.ExpectDB().WillReturn(m.NewDB())
   710  		},
   711  		test: func(t *testing.T, c *kivik.Client) { //nolint:thelper // Not a helper
   712  			db := c.DB("asd")
   713  			err := db.Err()
   714  			if !testy.ErrorMatches("", err) {
   715  				t.Errorf("Unexpected error: %s", err)
   716  			}
   717  			if db.Name() != "asd" {
   718  				t.Errorf("Unexpected db name: %s", db.Name())
   719  			}
   720  		},
   721  	})
   722  	tests.Run(t, testMock)
   723  }
   724  
   725  func TestCreateDB(t *testing.T) {
   726  	tests := testy.NewTable()
   727  	tests.Add("error", mockTest{
   728  		setup: func(m *Client) {
   729  			m.ExpectCreateDB().WillReturnError(errors.New("foo err"))
   730  		},
   731  		test: func(t *testing.T, c *kivik.Client) { //nolint:thelper // Not a helper
   732  			err := c.CreateDB(context.TODO(), "foo")
   733  			if !testy.ErrorMatches("foo err", err) {
   734  				t.Errorf("Unexpected error: %s", err)
   735  			}
   736  		},
   737  	})
   738  	tests.Add("name", mockTest{
   739  		setup: func(m *Client) {
   740  			m.ExpectCreateDB().WithName("foo")
   741  		},
   742  		test: func(t *testing.T, c *kivik.Client) { //nolint:thelper // Not a helper
   743  			err := c.CreateDB(context.TODO(), "foo")
   744  			if !testy.ErrorMatches("", err) {
   745  				t.Errorf("Unexpected error: %s", err)
   746  			}
   747  		},
   748  	})
   749  	tests.Add("unexpected", mockTest{
   750  		test: func(t *testing.T, c *kivik.Client) { //nolint:thelper // Not a helper
   751  			err := c.CreateDB(context.TODO(), "foo")
   752  			if !testy.ErrorMatches("call to CreateDB() was not expected, all expectations already fulfilled", err) {
   753  				t.Errorf("Unexpected error: %s", err)
   754  			}
   755  		},
   756  	})
   757  	tests.Add("options", mockTest{
   758  		setup: func(m *Client) {
   759  			m.ExpectCreateDB().WithOptions(kivik.Param("foo", 123))
   760  		},
   761  		test: func(t *testing.T, c *kivik.Client) { //nolint:thelper // Not a helper
   762  			err := c.CreateDB(context.TODO(), "foo", kivik.Param("foo", 123))
   763  			if !testy.ErrorMatches("", err) {
   764  				t.Errorf("Unexpected error: %s", err)
   765  			}
   766  		},
   767  	})
   768  	tests.Add("success", mockTest{
   769  		setup: func(m *Client) {
   770  			m.ExpectCreateDB()
   771  		},
   772  		test: func(t *testing.T, c *kivik.Client) { //nolint:thelper // Not a helper
   773  			err := c.CreateDB(context.TODO(), "foo")
   774  			if !testy.ErrorMatches("", err) {
   775  				t.Errorf("Unexpected error: %s", err)
   776  			}
   777  		},
   778  	})
   779  	tests.Add("delay", mockTest{
   780  		setup: func(m *Client) {
   781  			m.ExpectCreateDB().WillDelay(time.Second)
   782  		},
   783  		test: func(t *testing.T, c *kivik.Client) { //nolint:thelper // Not a helper
   784  			err := c.CreateDB(newCanceledContext(), "foo")
   785  			if !testy.ErrorMatches("context canceled", err) {
   786  				t.Errorf("Unexpected error: %s", err)
   787  			}
   788  		},
   789  	})
   790  	tests.Add("cleanup expectations", mockTest{
   791  		setup: func(m *Client) {
   792  			m.ExpectCreateDB().WillReturnError(errors.New("foo err"))
   793  		},
   794  		test: func(t *testing.T, c *kivik.Client) { //nolint:thelper // Not a helper
   795  			err := c.CreateDB(context.TODO(), "foo")
   796  			if err == nil {
   797  				t.Fatal("expected error")
   798  			}
   799  		},
   800  	})
   801  	tests.Add("callback", mockTest{
   802  		setup: func(m *Client) {
   803  			m.ExpectCreateDB().WillExecute(func(context.Context, string, driver.Options) error {
   804  				return errors.New("custom error")
   805  			})
   806  		},
   807  		test: func(t *testing.T, c *kivik.Client) { //nolint:thelper // Not a helper
   808  			err := c.CreateDB(context.TODO(), "foo")
   809  			if !testy.ErrorMatches("custom error", err) {
   810  				t.Errorf("Unexpected error: %s", err)
   811  			}
   812  		},
   813  	})
   814  	tests.Run(t, testMock)
   815  }
   816  
   817  func TestDBUpdates(t *testing.T) {
   818  	tests := testy.NewTable()
   819  	tests.Add("error", mockTest{
   820  		setup: func(m *Client) {
   821  			m.ExpectDBUpdates().WillReturnError(errors.New("foo err"))
   822  		},
   823  		test: func(t *testing.T, c *kivik.Client) { //nolint:thelper // Not a helper
   824  			rows := c.DBUpdates(context.TODO())
   825  			if err := rows.Err(); !testy.ErrorMatches("foo err", err) {
   826  				t.Errorf("Unexpected error: %s", err)
   827  			}
   828  		},
   829  	})
   830  	tests.Add("unexpected", mockTest{
   831  		test: func(t *testing.T, c *kivik.Client) { //nolint:thelper // Not a helper
   832  			rows := c.DBUpdates(context.TODO())
   833  			if err := rows.Err(); !testy.ErrorMatches("call to DBUpdates() was not expected, all expectations already fulfilled", err) {
   834  				t.Errorf("Unexpected error: %s", err)
   835  			}
   836  		},
   837  	})
   838  	tests.Add("close error", mockTest{
   839  		setup: func(m *Client) {
   840  			m.ExpectDBUpdates().WillReturn(NewDBUpdates().CloseError(errors.New("bar err")))
   841  		},
   842  		test: func(t *testing.T, c *kivik.Client) { //nolint:thelper // Not a helper
   843  			rows := c.DBUpdates(context.TODO())
   844  			if err := rows.Err(); !testy.ErrorMatches("", err) {
   845  				t.Errorf("Unexpected error: %s", err)
   846  			}
   847  			if err := rows.Close(); !testy.ErrorMatches("bar err", err) {
   848  				t.Errorf("Unexpected error: %s", err)
   849  			}
   850  		},
   851  	})
   852  	tests.Add("updates", mockTest{
   853  		setup: func(m *Client) {
   854  			m.ExpectDBUpdates().WillReturn(NewDBUpdates().
   855  				AddUpdate(&driver.DBUpdate{DBName: "foo"}).
   856  				AddUpdate(&driver.DBUpdate{DBName: "bar"}).
   857  				AddUpdate(&driver.DBUpdate{DBName: "baz"}))
   858  		},
   859  		test: func(t *testing.T, c *kivik.Client) { //nolint:thelper // Not a helper
   860  			rows := c.DBUpdates(context.TODO())
   861  			if err := rows.Err(); !testy.ErrorMatches("", err) {
   862  				t.Errorf("Unexpected error: %s", err)
   863  			}
   864  			names := []string{}
   865  			for rows.Next() {
   866  				names = append(names, rows.DBName())
   867  			}
   868  			expected := []string{"foo", "bar", "baz"}
   869  			if d := testy.DiffInterface(expected, names); d != nil {
   870  				t.Error(d)
   871  			}
   872  		},
   873  	})
   874  	tests.Add("iter error", mockTest{
   875  		setup: func(m *Client) {
   876  			m.ExpectDBUpdates().WillReturn(NewDBUpdates().
   877  				AddUpdate(&driver.DBUpdate{DBName: "foo"}).
   878  				AddUpdateError(errors.New("foo err")))
   879  		},
   880  		test: func(t *testing.T, c *kivik.Client) { //nolint:thelper // Not a helper
   881  			rows := c.DBUpdates(context.TODO())
   882  			if err := rows.Err(); !testy.ErrorMatches("", err) {
   883  				t.Errorf("Unexpected error: %s", err)
   884  			}
   885  			names := []string{}
   886  			for rows.Next() {
   887  				names = append(names, rows.DBName())
   888  			}
   889  			expected := []string{"foo"}
   890  			if d := testy.DiffInterface(expected, names); d != nil {
   891  				t.Error(d)
   892  			}
   893  			if err := rows.Err(); !testy.ErrorMatches("foo err", err) {
   894  				t.Errorf("Unexpected error: %s", err)
   895  			}
   896  		},
   897  	})
   898  	tests.Add("delay", mockTest{
   899  		setup: func(m *Client) {
   900  			m.ExpectDBUpdates().WillDelay(time.Second)
   901  		},
   902  		test: func(t *testing.T, c *kivik.Client) { //nolint:thelper // Not a helper
   903  			rows := c.DBUpdates(newCanceledContext())
   904  			if err := rows.Err(); !testy.ErrorMatches("context canceled", err) {
   905  				t.Errorf("Unexpected error: %s", err)
   906  			}
   907  		},
   908  	})
   909  	tests.Add("update delay", mockTest{
   910  		setup: func(m *Client) {
   911  			m.ExpectDBUpdates().WillReturn(NewDBUpdates().
   912  				AddDelay(time.Millisecond).
   913  				AddUpdate(&driver.DBUpdate{DBName: "foo"}).
   914  				AddDelay(time.Second).
   915  				AddUpdate(&driver.DBUpdate{DBName: "bar"}))
   916  		},
   917  		test: func(t *testing.T, c *kivik.Client) { //nolint:thelper // Not a helper
   918  			ctx, cancel := context.WithTimeout(context.Background(), 200*time.Millisecond)
   919  			defer cancel()
   920  			rows := c.DBUpdates(ctx)
   921  			if err := rows.Err(); !testy.ErrorMatches("", err) {
   922  				t.Errorf("Unexpected error: %s", err)
   923  			}
   924  			names := []string{}
   925  			for rows.Next() {
   926  				names = append(names, rows.DBName())
   927  			}
   928  			expected := []string{"foo"}
   929  			if d := testy.DiffInterface(expected, names); d != nil {
   930  				t.Error(d)
   931  			}
   932  			if err := rows.Err(); !testy.ErrorMatches("context deadline exceeded", err) {
   933  				t.Errorf("Unexpected error: %s", err)
   934  			}
   935  		},
   936  	})
   937  	tests.Run(t, testMock)
   938  }
   939  
   940  func TestConfig(t *testing.T) {
   941  	tests := testy.NewTable()
   942  	tests.Add("error", mockTest{
   943  		setup: func(m *Client) {
   944  			m.ExpectConfig().WillReturnError(errors.New("foo err"))
   945  		},
   946  		test: func(t *testing.T, c *kivik.Client) { //nolint:thelper // Not a helper
   947  			_, err := c.Config(context.TODO(), "local")
   948  			if !testy.ErrorMatches("foo err", err) {
   949  				t.Errorf("Unexpected error: %s", err)
   950  			}
   951  		},
   952  	})
   953  	tests.Add("unexpected", mockTest{
   954  		test: func(t *testing.T, c *kivik.Client) { //nolint:thelper // Not a helper
   955  			_, err := c.Config(context.TODO(), "local")
   956  			if !testy.ErrorMatches("call to Config() was not expected, all expectations already fulfilled", err) {
   957  				t.Errorf("Unexpected error: %s", err)
   958  			}
   959  		},
   960  	})
   961  	tests.Add("delay", mockTest{
   962  		setup: func(m *Client) {
   963  			m.ExpectConfig().WillDelay(time.Second)
   964  		},
   965  		test: func(t *testing.T, c *kivik.Client) { //nolint:thelper // Not a helper
   966  			_, err := c.Config(newCanceledContext(), "local")
   967  			if !testy.ErrorMatches("context canceled", err) {
   968  				t.Errorf("Unexpected error: %s", err)
   969  			}
   970  		},
   971  	})
   972  	tests.Add("success", func() interface{} {
   973  		expected := kivik.Config{"foo": kivik.ConfigSection{"bar": "baz"}}
   974  		return mockTest{
   975  			setup: func(m *Client) {
   976  				m.ExpectConfig().
   977  					WithNode("local").
   978  					WillReturn(driver.Config{"foo": driver.ConfigSection{"bar": "baz"}})
   979  			},
   980  			test: func(t *testing.T, c *kivik.Client) { //nolint:thelper // Not a helper
   981  				result, err := c.Config(newCanceledContext(), "local")
   982  				if !testy.ErrorMatches("", err) {
   983  					t.Errorf("Unexpected error: %s", err)
   984  				}
   985  				if d := testy.DiffInterface(expected, result); d != nil {
   986  					t.Error(d)
   987  				}
   988  			},
   989  		}
   990  	})
   991  
   992  	tests.Run(t, testMock)
   993  }
   994  
   995  func TestConfigSection(t *testing.T) {
   996  	tests := testy.NewTable()
   997  	tests.Add("error", mockTest{
   998  		setup: func(m *Client) {
   999  			m.ExpectConfigSection().WillReturnError(errors.New("foo err"))
  1000  		},
  1001  		test: func(t *testing.T, c *kivik.Client) { //nolint:thelper // Not a helper
  1002  			_, err := c.ConfigSection(context.TODO(), "local", "foo")
  1003  			if !testy.ErrorMatches("foo err", err) {
  1004  				t.Errorf("Unexpected error: %s", err)
  1005  			}
  1006  		},
  1007  	})
  1008  	tests.Add("unexpected", mockTest{
  1009  		test: func(t *testing.T, c *kivik.Client) { //nolint:thelper // Not a helper
  1010  			_, err := c.ConfigSection(context.TODO(), "local", "foo")
  1011  			if !testy.ErrorMatches("call to ConfigSection() was not expected, all expectations already fulfilled", err) {
  1012  				t.Errorf("Unexpected error: %s", err)
  1013  			}
  1014  		},
  1015  	})
  1016  	tests.Add("delay", mockTest{
  1017  		setup: func(m *Client) {
  1018  			m.ExpectConfigSection().WillDelay(time.Second)
  1019  		},
  1020  		test: func(t *testing.T, c *kivik.Client) { //nolint:thelper // Not a helper
  1021  			_, err := c.ConfigSection(newCanceledContext(), "local", "foo")
  1022  			if !testy.ErrorMatches("context canceled", err) {
  1023  				t.Errorf("Unexpected error: %s", err)
  1024  			}
  1025  		},
  1026  	})
  1027  	tests.Add("success", func() interface{} {
  1028  		expected := kivik.ConfigSection{"bar": "baz"}
  1029  		return mockTest{
  1030  			setup: func(m *Client) {
  1031  				m.ExpectConfigSection().
  1032  					WithNode("local").
  1033  					WithSection("foo").
  1034  					WillReturn(driver.ConfigSection{"bar": "baz"})
  1035  			},
  1036  			test: func(t *testing.T, c *kivik.Client) { //nolint:thelper // Not a helper
  1037  				result, err := c.ConfigSection(newCanceledContext(), "local", "foo")
  1038  				if !testy.ErrorMatches("", err) {
  1039  					t.Errorf("Unexpected error: %s", err)
  1040  				}
  1041  				if d := testy.DiffInterface(expected, result); d != nil {
  1042  					t.Error(d)
  1043  				}
  1044  			},
  1045  		}
  1046  	})
  1047  
  1048  	tests.Run(t, testMock)
  1049  }
  1050  
  1051  func TestConfigValue(t *testing.T) {
  1052  	tests := testy.NewTable()
  1053  	tests.Add("error", mockTest{
  1054  		setup: func(m *Client) {
  1055  			m.ExpectConfigValue().WillReturnError(errors.New("foo err"))
  1056  		},
  1057  		test: func(t *testing.T, c *kivik.Client) { //nolint:thelper // Not a helper
  1058  			_, err := c.ConfigValue(context.TODO(), "local", "foo", "bar")
  1059  			if !testy.ErrorMatches("foo err", err) {
  1060  				t.Errorf("Unexpected error: %s", err)
  1061  			}
  1062  		},
  1063  	})
  1064  	tests.Add("unexpected", mockTest{
  1065  		test: func(t *testing.T, c *kivik.Client) { //nolint:thelper // Not a helper
  1066  			_, err := c.ConfigValue(context.TODO(), "local", "foo", "bar")
  1067  			if !testy.ErrorMatches("call to ConfigValue() was not expected, all expectations already fulfilled", err) {
  1068  				t.Errorf("Unexpected error: %s", err)
  1069  			}
  1070  		},
  1071  	})
  1072  	tests.Add("delay", mockTest{
  1073  		setup: func(m *Client) {
  1074  			m.ExpectConfigValue().WillDelay(time.Second)
  1075  		},
  1076  		test: func(t *testing.T, c *kivik.Client) { //nolint:thelper // Not a helper
  1077  			_, err := c.ConfigValue(newCanceledContext(), "local", "foo", "bar")
  1078  			if !testy.ErrorMatches("context canceled", err) {
  1079  				t.Errorf("Unexpected error: %s", err)
  1080  			}
  1081  		},
  1082  	})
  1083  	tests.Add("success", func() interface{} {
  1084  		expected := "baz"
  1085  		return mockTest{
  1086  			setup: func(m *Client) {
  1087  				m.ExpectConfigValue().
  1088  					WithNode("local").
  1089  					WithSection("foo").
  1090  					WithKey("bar").
  1091  					WillReturn("baz")
  1092  			},
  1093  			test: func(t *testing.T, c *kivik.Client) { //nolint:thelper // Not a helper
  1094  				result, err := c.ConfigValue(newCanceledContext(), "local", "foo", "bar")
  1095  				if !testy.ErrorMatches("", err) {
  1096  					t.Errorf("Unexpected error: %s", err)
  1097  				}
  1098  				if d := testy.DiffInterface(expected, result); d != nil {
  1099  					t.Error(d)
  1100  				}
  1101  			},
  1102  		}
  1103  	})
  1104  
  1105  	tests.Run(t, testMock)
  1106  }
  1107  
  1108  func TestSetConfigValue(t *testing.T) {
  1109  	tests := testy.NewTable()
  1110  	tests.Add("error", mockTest{
  1111  		setup: func(m *Client) {
  1112  			m.ExpectSetConfigValue().WillReturnError(errors.New("foo err"))
  1113  		},
  1114  		test: func(t *testing.T, c *kivik.Client) { //nolint:thelper // Not a helper
  1115  			_, err := c.SetConfigValue(context.TODO(), "local", "foo", "bar", "baz")
  1116  			if !testy.ErrorMatches("foo err", err) {
  1117  				t.Errorf("Unexpected error: %s", err)
  1118  			}
  1119  		},
  1120  	})
  1121  	tests.Add("unexpected", mockTest{
  1122  		test: func(t *testing.T, c *kivik.Client) { //nolint:thelper // Not a helper
  1123  			_, err := c.SetConfigValue(context.TODO(), "local", "foo", "bar", "baz")
  1124  			if !testy.ErrorMatches("call to SetConfigValue() was not expected, all expectations already fulfilled", err) {
  1125  				t.Errorf("Unexpected error: %s", err)
  1126  			}
  1127  		},
  1128  	})
  1129  	tests.Add("delay", mockTest{
  1130  		setup: func(m *Client) {
  1131  			m.ExpectSetConfigValue().WillDelay(time.Second)
  1132  		},
  1133  		test: func(t *testing.T, c *kivik.Client) { //nolint:thelper // Not a helper
  1134  			_, err := c.SetConfigValue(newCanceledContext(), "local", "foo", "bar", "baz")
  1135  			if !testy.ErrorMatches("context canceled", err) {
  1136  				t.Errorf("Unexpected error: %s", err)
  1137  			}
  1138  		},
  1139  	})
  1140  	tests.Add("success", func() interface{} {
  1141  		expected := "old"
  1142  		return mockTest{
  1143  			setup: func(m *Client) {
  1144  				m.ExpectSetConfigValue().
  1145  					WithNode("local").
  1146  					WithSection("foo").
  1147  					WithKey("bar").
  1148  					WithValue("baz").
  1149  					WillReturn("old")
  1150  			},
  1151  			test: func(t *testing.T, c *kivik.Client) { //nolint:thelper // Not a helper
  1152  				result, err := c.SetConfigValue(newCanceledContext(), "local", "foo", "bar", "baz")
  1153  				if !testy.ErrorMatches("", err) {
  1154  					t.Errorf("Unexpected error: %s", err)
  1155  				}
  1156  				if d := testy.DiffInterface(expected, result); d != nil {
  1157  					t.Error(d)
  1158  				}
  1159  			},
  1160  		}
  1161  	})
  1162  
  1163  	tests.Run(t, testMock)
  1164  }
  1165  
  1166  func TestDeleteConfigKey(t *testing.T) {
  1167  	tests := testy.NewTable()
  1168  	tests.Add("error", mockTest{
  1169  		setup: func(m *Client) {
  1170  			m.ExpectDeleteConfigKey().WillReturnError(errors.New("foo err"))
  1171  		},
  1172  		test: func(t *testing.T, c *kivik.Client) { //nolint:thelper // Not a helper
  1173  			_, err := c.DeleteConfigKey(context.TODO(), "local", "foo", "bar")
  1174  			if !testy.ErrorMatches("foo err", err) {
  1175  				t.Errorf("Unexpected error: %s", err)
  1176  			}
  1177  		},
  1178  	})
  1179  	tests.Add("unexpected", mockTest{
  1180  		test: func(t *testing.T, c *kivik.Client) { //nolint:thelper // Not a helper
  1181  			_, err := c.DeleteConfigKey(context.TODO(), "local", "foo", "bar")
  1182  			if !testy.ErrorMatches("call to DeleteConfigKey() was not expected, all expectations already fulfilled", err) {
  1183  				t.Errorf("Unexpected error: %s", err)
  1184  			}
  1185  		},
  1186  	})
  1187  	tests.Add("delay", mockTest{
  1188  		setup: func(m *Client) {
  1189  			m.ExpectDeleteConfigKey().WillDelay(time.Second)
  1190  		},
  1191  		test: func(t *testing.T, c *kivik.Client) { //nolint:thelper // Not a helper
  1192  			_, err := c.DeleteConfigKey(newCanceledContext(), "local", "foo", "bar")
  1193  			if !testy.ErrorMatches("context canceled", err) {
  1194  				t.Errorf("Unexpected error: %s", err)
  1195  			}
  1196  		},
  1197  	})
  1198  	tests.Add("success", func() interface{} {
  1199  		expected := "old"
  1200  		return mockTest{
  1201  			setup: func(m *Client) {
  1202  				m.ExpectDeleteConfigKey().
  1203  					WithNode("local").
  1204  					WithSection("foo").
  1205  					WithKey("bar").
  1206  					WillReturn("old")
  1207  			},
  1208  			test: func(t *testing.T, c *kivik.Client) { //nolint:thelper // Not a helper
  1209  				result, err := c.DeleteConfigKey(newCanceledContext(), "local", "foo", "bar")
  1210  				if !testy.ErrorMatches("", err) {
  1211  					t.Errorf("Unexpected error: %s", err)
  1212  				}
  1213  				if d := testy.DiffInterface(expected, result); d != nil {
  1214  					t.Error(d)
  1215  				}
  1216  			},
  1217  		}
  1218  	})
  1219  
  1220  	tests.Run(t, testMock)
  1221  }
  1222  
  1223  func TestReplicate(t *testing.T) {
  1224  	tests := testy.NewTable()
  1225  	tests.Add("err", mockTest{
  1226  		setup: func(m *Client) {
  1227  			m.ExpectReplicate().WillReturnError(errors.New("replicate failed"))
  1228  		},
  1229  		test: func(t *testing.T, c *kivik.Client) { //nolint:thelper // Not a helper
  1230  			_, err := c.Replicate(context.TODO(), "foo", "bar")
  1231  			if !testy.ErrorMatches("replicate failed", err) {
  1232  				t.Errorf("Unexpected error: %s", err)
  1233  			}
  1234  		},
  1235  	})
  1236  	tests.Add("unexpected", mockTest{
  1237  		test: func(t *testing.T, c *kivik.Client) { //nolint:thelper // Not a helper
  1238  			_, err := c.Replicate(context.TODO(), "foo", "bar")
  1239  			if !testy.ErrorMatches("call to Replicate() was not expected, all expectations already fulfilled", err) {
  1240  				t.Errorf("Unexpected error: %s", err)
  1241  			}
  1242  		},
  1243  	})
  1244  	tests.Add("source and target", mockTest{
  1245  		setup: func(m *Client) {
  1246  			m.ExpectReplicate().
  1247  				WithSource("bar").
  1248  				WithTarget("foo").
  1249  				WillReturnError(errors.New("expected"))
  1250  		},
  1251  		test: func(t *testing.T, c *kivik.Client) { //nolint:thelper // Not a helper
  1252  			_, err := c.Replicate(context.TODO(), "foo", "bar")
  1253  			if !testy.ErrorMatches("expected", err) {
  1254  				t.Errorf("Unexpected error: %s", err)
  1255  			}
  1256  		},
  1257  	})
  1258  	tests.Add("return", mockTest{
  1259  		setup: func(m *Client) {
  1260  			r := m.NewReplication().ID("aaa")
  1261  			m.ExpectReplicate().
  1262  				WillReturn(r)
  1263  		},
  1264  		test: func(t *testing.T, c *kivik.Client) { //nolint:thelper // Not a helper
  1265  			rep, err := c.Replicate(context.TODO(), "foo", "bar")
  1266  			if !testy.ErrorMatches("", err) {
  1267  				t.Errorf("Unexpected error: %s", err)
  1268  			}
  1269  			if id := rep.ReplicationID(); id != "aaa" {
  1270  				t.Errorf("Unexpected replication ID: %s", id)
  1271  			}
  1272  		},
  1273  	})
  1274  	tests.Add("delay", mockTest{
  1275  		setup: func(m *Client) {
  1276  			m.ExpectReplicate().WillDelay(time.Second)
  1277  		},
  1278  		test: func(t *testing.T, c *kivik.Client) { //nolint:thelper // Not a helper
  1279  			_, err := c.Replicate(newCanceledContext(), "foo", "bar")
  1280  			if !testy.ErrorMatches("context canceled", err) {
  1281  				t.Errorf("Unexpected error: %s", err)
  1282  			}
  1283  		},
  1284  	})
  1285  	tests.Run(t, testMock)
  1286  }
  1287  
  1288  func TestGetReplications(t *testing.T) {
  1289  	tests := testy.NewTable()
  1290  	tests.Add("err", mockTest{
  1291  		setup: func(m *Client) {
  1292  			m.ExpectGetReplications().WillReturnError(errors.New("get replications failed"))
  1293  		},
  1294  		test: func(t *testing.T, c *kivik.Client) { //nolint:thelper // Not a helper
  1295  			_, err := c.GetReplications(context.TODO())
  1296  			if !testy.ErrorMatches("get replications failed", err) {
  1297  				t.Errorf("Unexpected error: %s", err)
  1298  			}
  1299  		},
  1300  	})
  1301  	tests.Add("unexpected", mockTest{
  1302  		test: func(t *testing.T, c *kivik.Client) { //nolint:thelper // Not a helper
  1303  			_, err := c.GetReplications(context.TODO())
  1304  			if !testy.ErrorMatches("call to GetReplications() was not expected, all expectations already fulfilled", err) {
  1305  				t.Errorf("Unexpected error: %s", err)
  1306  			}
  1307  		},
  1308  	})
  1309  	tests.Add("return", mockTest{
  1310  		setup: func(m *Client) {
  1311  			m.ExpectGetReplications().
  1312  				WillReturn([]*Replication{
  1313  					m.NewReplication().ID("bbb"),
  1314  					m.NewReplication().ID("ccc"),
  1315  				})
  1316  		},
  1317  		test: func(t *testing.T, c *kivik.Client) { //nolint:thelper // Not a helper
  1318  			reps, err := c.GetReplications(context.TODO())
  1319  			if !testy.ErrorMatches("", err) {
  1320  				t.Errorf("Unexpected error: %s", err)
  1321  			}
  1322  			if id := reps[0].ReplicationID(); id != "bbb" {
  1323  				t.Errorf("Unexpected replication 1 ID: %s", id)
  1324  			}
  1325  			if id := reps[1].ReplicationID(); id != "ccc" {
  1326  				t.Errorf("Unexpected replication 2 ID: %s", id)
  1327  			}
  1328  		},
  1329  	})
  1330  	tests.Add("delay", mockTest{
  1331  		setup: func(m *Client) {
  1332  			m.ExpectGetReplications().WillDelay(time.Second)
  1333  		},
  1334  		test: func(t *testing.T, c *kivik.Client) { //nolint:thelper // Not a helper
  1335  			_, err := c.GetReplications(newCanceledContext())
  1336  			if !testy.ErrorMatches("context canceled", err) {
  1337  				t.Errorf("Unexpected error: %s", err)
  1338  			}
  1339  		},
  1340  	})
  1341  	tests.Run(t, testMock)
  1342  }
  1343  

View as plain text