github.com/qri-io/qri@v0.10.1-0.20220104210721-c771715036cb/cmd/get_test.go (about)

     1  package cmd
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"testing"
     7  
     8  	"github.com/google/go-cmp/cmp"
     9  	"github.com/qri-io/dataset/dstest"
    10  )
    11  
    12  func TestGetComplete(t *testing.T) {
    13  	run := NewTestRunner(t, "test_peer_get", "qri_test_get_complete")
    14  	defer run.Delete()
    15  
    16  	ctx, cancel := context.WithCancel(context.Background())
    17  	defer cancel()
    18  
    19  	f, err := NewTestFactory(ctx)
    20  	if err != nil {
    21  		t.Errorf("error creating new test factory: %s", err)
    22  		return
    23  	}
    24  
    25  	cases := []struct {
    26  		args     []string
    27  		selector string
    28  		refs     []string
    29  		err      string
    30  	}{
    31  		{[]string{}, "", []string{}, ""},
    32  		{[]string{"one arg"}, "", []string{"one arg"}, ""},
    33  		{[]string{"commit", "peer/ds"}, "commit", []string{"peer/ds"}, ""},
    34  		{[]string{"commit.author", "peer/ds"}, "commit.author", []string{"peer/ds"}, ""},
    35  		// TODO(dlong): Fix tests when `qri get` can be passed multiple arguments.
    36  		//{[]string{"peer/ds_two", "peer/ds"}, "", []string{"peer/ds_two", "peer/ds"}, ""},
    37  		//{[]string{"foo", "peer/ds"}, "", []string{"foo", "peer/ds"}, ""},
    38  		{[]string{"structure"}, "structure", []string{}, ""},
    39  		{[]string{"stats", "me/cities"}, "stats", []string{"me/cities"}, ""},
    40  		{[]string{"stats", "me/sitemap"}, "stats", []string{"me/sitemap"}, ""},
    41  	}
    42  
    43  	for i, c := range cases {
    44  		opt := &GetOptions{
    45  			IOStreams: run.Streams,
    46  		}
    47  
    48  		opt.Complete(f, c.args)
    49  
    50  		if c.err != run.ErrStream.String() {
    51  			t.Errorf("case %d, error mismatch. Expected: '%s', Got: '%s'", i, c.err, run.ErrStream.String())
    52  			run.IOReset()
    53  			continue
    54  		}
    55  
    56  		if !testSliceEqual(c.refs, opt.Refs.RefList()) {
    57  			t.Errorf("case %d, opt.Refs not set correctly. Expected: '%q', Got: '%q'", i, c.refs, opt.Refs.RefList())
    58  			run.IOReset()
    59  			continue
    60  		}
    61  
    62  		if c.selector != opt.Selector {
    63  			t.Errorf("case %d, opt.Selector not set correctly. Expected: '%s', Got: '%s'", i, c.selector, opt.Selector)
    64  			run.IOReset()
    65  			continue
    66  		}
    67  
    68  		if opt.inst == nil {
    69  			t.Errorf("case %d, opt.inst not set.", i)
    70  			run.IOReset()
    71  			continue
    72  		}
    73  		run.IOReset()
    74  	}
    75  }
    76  
    77  const (
    78  	currHeadRepo = `body:{{ .body }}
    79  bodyPath: {{ .bodyPath }}
    80  commit:
    81    author:
    82      id: {{ .profileID }}
    83    message: "body:\n\tchanged by 54%"
    84    path: {{ .commitPath }}
    85    qri: cm:0
    86    signature: {{ .signature }}
    87    timestamp: "2001-01-01T01:02:01.000000001Z"
    88    title: body changed by 54%
    89  id: {{ .id }}
    90  name: my_ds
    91  path: {{ .path }}
    92  peername: test_peer_get
    93  previousPath: {{ .previousPath }}
    94  qri: ds:0
    95  stats:
    96    path: {{ .statsPath }}
    97    qri: sa:0
    98    stats:
    99    - count: 18
   100      frequencies:
   101        'Avatar ': 1
   102        'Avengers: Age of Ultron ': 1
   103        'Batman v Superman: Dawn of Justice ': 1
   104        'Harry Potter and the Half-Blood Prince ': 1
   105        'John Carter ': 1
   106        'Man of Steel ': 1
   107        'Pirates of the Caribbean: At World''s End... 41 chars (6)': 1
   108        'Pirates of the Caribbean: Dead Man''s Che... 43 chars (7)': 1
   109        'Quantum of Solace ': 1
   110        'Spectre ': 1
   111        'Spider-Man 3 ': 1
   112        'Star Wars: Episode VII - The Force Awake... 55 chars (11)': 1
   113        'Superman Returns ': 1
   114        'Tangled ': 1
   115        'The Avengers ': 1
   116        'The Chronicles of Narnia: Prince Caspian... 41 chars (15)': 1
   117        'The Dark Knight Rises ': 1
   118        'The Lone Ranger ': 1
   119      maxLength: 55
   120      minLength: 7
   121      type: string
   122      unique: 18
   123    - count: 17
   124      histogram:
   125        bins:
   126        - 100
   127        - 106
   128        - 132
   129        - 141
   130        - 143
   131        - 148
   132        - 150
   133        - 151
   134        - 153
   135        - 156
   136        - 164
   137        - 169
   138        - 173
   139        - 178
   140        - 183
   141        - 184
   142        frequencies:
   143        - 1
   144        - 1
   145        - 1
   146        - 1
   147        - 1
   148        - 1
   149        - 2
   150        - 1
   151        - 1
   152        - 1
   153        - 1
   154        - 2
   155        - 1
   156        - 1
   157        - 1
   158      max: 183
   159      mean: 150.94117647058823
   160      median: 151
   161      min: 100
   162      type: numeric
   163  structure:
   164    checksum: {{ .bodyPath }}
   165    depth: 2
   166    entries: 18
   167    errCount: 1
   168    format: csv
   169    formatConfig:
   170      headerRow: true
   171      lazyQuotes: true
   172    length: 532
   173    path: {{ .structurePath }}
   174    qri: st:0
   175    schema:
   176      items:
   177        items:
   178        - title: movie_title
   179          type: string
   180        - title: duration
   181          type: integer
   182        type: array
   183      type: array
   184  
   185  `
   186  
   187  	prevHeadRepo = `body:{{ .body }}
   188  bodyPath: {{ .bodyPath }}
   189  commit:
   190    author:
   191      id: {{ .profileID }}
   192    message: created dataset from body_ten.csv
   193    path: {{ .commitPath }}
   194    qri: cm:0
   195    signature: {{ .signature }}
   196    timestamp: "2001-01-01T01:01:01.000000001Z"
   197    title: created dataset from body_ten.csv
   198  id: {{ .id }}
   199  name: my_ds
   200  path: {{ .path }}
   201  peername: test_peer_get
   202  qri: ds:0
   203  stats:
   204    path: {{ .statsPath }}
   205    qri: sa:0
   206    stats:
   207    - count: 8
   208      frequencies:
   209        'Avatar ': 1
   210        'John Carter ': 1
   211        'Pirates of the Caribbean: At World''s End... 41 chars (2)': 1
   212        'Spectre ': 1
   213        'Spider-Man 3 ': 1
   214        'Star Wars: Episode VII - The Force Awake... 55 chars (5)': 1
   215        'Tangled ': 1
   216        'The Dark Knight Rises ': 1
   217      maxLength: 55
   218      minLength: 7
   219      type: string
   220      unique: 8
   221    - count: 7
   222      histogram:
   223        bins:
   224        - 100
   225        - 132
   226        - 148
   227        - 156
   228        - 164
   229        - 169
   230        - 178
   231        - 179
   232        frequencies:
   233        - 1
   234        - 1
   235        - 1
   236        - 1
   237        - 1
   238        - 1
   239        - 1
   240      max: 178
   241      mean: 149.57142857142858
   242      median: 156
   243      min: 100
   244      type: numeric
   245  structure:
   246    checksum: {{ .bodyPath }}
   247    depth: 2
   248    entries: 8
   249    errCount: 1
   250    format: csv
   251    formatConfig:
   252      headerRow: true
   253      lazyQuotes: true
   254    length: 224
   255    path: {{ .structurePath }}
   256    qri: st:0
   257    schema:
   258      items:
   259        items:
   260        - title: movie_title
   261          type: string
   262        - title: duration
   263          type: integer
   264        type: array
   265      type: array
   266  
   267  `
   268  	currBodyRepo = `movie_title,duration
   269  Avatar ,178
   270  Pirates of the Caribbean: At World's End ,169
   271  Spectre ,148
   272  The Dark Knight Rises ,164
   273  Star Wars: Episode VII - The Force Awakens             ,
   274  John Carter ,132
   275  Spider-Man 3 ,156
   276  Tangled ,100
   277  Avengers: Age of Ultron ,141
   278  Harry Potter and the Half-Blood Prince ,153
   279  Batman v Superman: Dawn of Justice ,183
   280  Superman Returns ,169
   281  Quantum of Solace ,106
   282  Pirates of the Caribbean: Dead Man's Chest ,151
   283  The Lone Ranger ,150
   284  Man of Steel ,143
   285  The Chronicles of Narnia: Prince Caspian ,150
   286  The Avengers ,173
   287  
   288  `
   289  	currBodyJSON = `[["Avatar ",178],["Pirates of the Caribbean: At World's End ",169],["Spectre ",148],["The Dark Knight Rises ",164],["Star Wars: Episode VII - The Force Awakens             ",""],["John Carter ",132],["Spider-Man 3 ",156],["Tangled ",100],["Avengers: Age of Ultron ",141],["Harry Potter and the Half-Blood Prince ",153],["Batman v Superman: Dawn of Justice ",183],["Superman Returns ",169],["Quantum of Solace ",106],["Pirates of the Caribbean: Dead Man's Chest ",151],["The Lone Ranger ",150],["Man of Steel ",143],["The Chronicles of Narnia: Prince Caspian ",150],["The Avengers ",173]]
   290  `
   291  
   292  	currBodyYAML = `
   293  - - 'Avatar '
   294    - 178
   295  - - 'Pirates of the Caribbean: At World''s End '
   296    - 169
   297  - - 'Spectre '
   298    - 148
   299  - - 'The Dark Knight Rises '
   300    - 164
   301  - - 'Star Wars: Episode VII - The Force Awakens             '
   302    - ""
   303  - - 'John Carter '
   304    - 132
   305  - - 'Spider-Man 3 '
   306    - 156
   307  - - 'Tangled '
   308    - 100
   309  - - 'Avengers: Age of Ultron '
   310    - 141
   311  - - 'Harry Potter and the Half-Blood Prince '
   312    - 153
   313  - - 'Batman v Superman: Dawn of Justice '
   314    - 183
   315  - - 'Superman Returns '
   316    - 169
   317  - - 'Quantum of Solace '
   318    - 106
   319  - - 'Pirates of the Caribbean: Dead Man''s Chest '
   320    - 151
   321  - - 'The Lone Ranger '
   322    - 150
   323  - - 'Man of Steel '
   324    - 143
   325  - - 'The Chronicles of Narnia: Prince Caspian '
   326    - 150
   327  - - 'The Avengers '
   328    - 173`
   329  
   330  	prevBodyRepo = `movie_title,duration
   331  Avatar ,178
   332  Pirates of the Caribbean: At World's End ,169
   333  Spectre ,148
   334  The Dark Knight Rises ,164
   335  Star Wars: Episode VII - The Force Awakens             ,
   336  John Carter ,132
   337  Spider-Man 3 ,156
   338  Tangled ,100
   339  
   340  `
   341  	prevBodyJSON = `[["Avatar ",178],["Pirates of the Caribbean: At World's End ",169],["Spectre ",148],["The Dark Knight Rises ",164],["Star Wars: Episode VII - The Force Awakens             ",""],["John Carter ",132],["Spider-Man 3 ",156],["Tangled ",100]]
   342  `
   343  
   344  	prevBodyYAML = `
   345  - - 'Avatar '
   346    - 178
   347  - - 'Pirates of the Caribbean: At World''s End '
   348    - 169
   349  - - 'Spectre '
   350    - 148
   351  - - 'The Dark Knight Rises '
   352    - 164
   353  - - 'Star Wars: Episode VII - The Force Awakens             '
   354    - ""
   355  - - 'John Carter '
   356    - 132
   357  - - 'Spider-Man 3 '
   358    - 156
   359  - - 'Tangled '
   360    - 100`
   361  )
   362  
   363  var (
   364  	currHeadRepoData = map[string]string{
   365  		"id":            "nkt3s27sojzsiu7tcs6p5asrwbqf3yd5nhjtotsstd6ub2owecvq",
   366  		"profileID":     "QmeL2mdVka1eahKENjehK6tBxkkpk5dNQ1qMcgWi7Hrb4B",
   367  		"body":          currBodyYAML,
   368  		"bodyPath":      "/ipfs/QmeLmPMNSCxVxCdDmdunBCfiN1crb3C2eUnZex6QgHpFiB",
   369  		"commitPath":    "/ipfs/QmQb3AfjzFn5RWGkrcFHV4GEDWAt97P9q3JhM8qJm69wZ3",
   370  		"signature":     "hK9sMkmsRqH8xKDNxTwQX0IfDsHX8wB08SQA/tz0R8V0QaWfPgjPBhvFvWXKXtM+UqxKDp1YzGLyAcozk7BIgRLPEcQI+TMvjpqf9UKlu7f0pmtnT6w7Vj8hHcVk/yvG+MfpKLWIK+FLWqIj46aeYztjtweN2AC1Xebky7ISzkczaOg0rL6hcbWoxE96Eqw5mvcX3iO9l/zfbF6GkRAhzKVHkNdmwvqPaMRE/XTdR9+F5bIodwpqJGmqM7igewimGQAe/UTyFhOYi7Z7LJxCGKeKJ/7n8mk7CfRQPmhqk8hzcVm5yTNjTUOUueK9Os1g8b3z6FgnWpIaMOV0L/ARqg==",
   371  		"path":          "/ipfs/Qmc75sMYi6fjvcKiRqsFFopjLYDTnuQ8BdesEUYoX5raG5",
   372  		"previousPath":  "/ipfs/QmVmAAVSVewv6HzojRBr2bqJgWwZ8w18vVPqQ6VuTuH7UZ",
   373  		"statsPath":     "/ipfs/Qmc3QsRMdo1rqY3F5Shr2Kd25yib6R4Ktgz3RdXTXwVjDU",
   374  		"structurePath": "/ipfs/QmcAfMfZ7qTNiCfQxnRJyDxEDM7tqDstvpgviT73PFbabZ",
   375  	}
   376  	prevHeadRepoData = map[string]string{
   377  		"id":            "nkt3s27sojzsiu7tcs6p5asrwbqf3yd5nhjtotsstd6ub2owecvq",
   378  		"profileID":     "QmeL2mdVka1eahKENjehK6tBxkkpk5dNQ1qMcgWi7Hrb4B",
   379  		"body":          prevBodyYAML,
   380  		"bodyPath":      "/ipfs/QmXhsUK6vGZrqarhw9Z8RCXqhmEpvtVByKtaYVarbDZ5zn",
   381  		"commitPath":    "/ipfs/QmRQo5ivNLbQdu1ps3iyEaVknyTYisUwsL152dwSorskJB",
   382  		"signature":     "iGs2R/GWE8f0YqRhTnaw6r/geX+5hSmTxOG68vdYbJ5dkqLXcp7nYkuezvs9aHPTLPgqoshJ6w0va8JthSSGkRkm6ue5iItLqN0Vbi2Ru/b7BAfvpJwoeb/FJCj41bFtqojs9S9flNJB7RmQl03usiaauUw/dkNE7KXZkT0DGA3Fo8cHKeAgyhYdZzPeXKu1RIp+rIMZMJOwj0Rw7oLBXjiWcqttwJQsvx8qAS72xhQZysGGicImdTPzeTK+7wwBnm99f2afjB1v3TD7h5XMmFRiOBtNx3U6snzTcUPvGeL895Q7ZBco9fEAPhgxgrV51b28IS0ci6qXyYfIOKNARg==",
   383  		"path":          "/ipfs/QmVmAAVSVewv6HzojRBr2bqJgWwZ8w18vVPqQ6VuTuH7UZ",
   384  		"previousPath":  "/ipfs/QmRQYDZMgrxE8SLQXKRxJRZRDshQwJBDdb2d27ZNFiVghM",
   385  		"statsPath":     "/ipfs/QmbJeH82n56LBGBsRWxmSctrUy1Urr1epePSpQ8bMgufsG",
   386  		"structurePath": "/ipfs/QmSxuAVwd9pPf9c7WMu1gjUsHSLBLRuxQcFjyu9mfsA2TQ",
   387  	}
   388  )
   389  
   390  func TestGetDatasetFromRepo(t *testing.T) {
   391  	run := NewTestRunner(t, "test_peer_get", "get_dataset_head")
   392  	defer run.Delete()
   393  
   394  	// Save two versions.
   395  	got := run.MustExecCombinedOutErr(t, "qri save --body=testdata/movies/body_ten.csv me/my_ds")
   396  	ref := parseRefFromSave(got)
   397  	run.MustExec(t, "qri save --body=testdata/movies/body_twenty.csv me/my_ds")
   398  
   399  	// Get head.
   400  	output := run.MustExec(t, "qri get me/my_ds")
   401  	expect := dstest.Template(t, currHeadRepo, currHeadRepoData)
   402  	if diff := cmp.Diff(expect, output); diff != "" {
   403  		t.Errorf("unexpected (-want +got):\n%s", diff)
   404  	}
   405  
   406  	// Get one version ago.
   407  	output = run.MustExec(t, fmt.Sprintf("qri get %s", ref))
   408  	expect = dstest.Template(t, prevHeadRepo, prevHeadRepoData)
   409  	if diff := cmp.Diff(expect, output); diff != "" {
   410  		t.Errorf("unexpected (-want +got):\n%s", diff)
   411  	}
   412  
   413  	// Get body from current commit in csv format
   414  	output = run.MustExec(t, "qri get body me/my_ds --format csv")
   415  	expect = currBodyRepo
   416  	if diff := cmp.Diff(expect, output); diff != "" {
   417  		t.Errorf("unexpected (-want +got):\n%s", diff)
   418  	}
   419  
   420  	// Get body from current commit in json format
   421  	output = run.MustExec(t, "qri get body me/my_ds")
   422  	expect = currBodyJSON
   423  	if diff := cmp.Diff(expect, output); diff != "" {
   424  		t.Errorf("unexpected (-want +got):\n%s", diff)
   425  	}
   426  
   427  	// Get body from one version ago in csv format
   428  	output = run.MustExec(t, fmt.Sprintf("qri get body %s --format csv", ref))
   429  	expect = prevBodyRepo
   430  	if diff := cmp.Diff(expect, output); diff != "" {
   431  		t.Errorf("unexpected (-want +got):\n%s", diff)
   432  	}
   433  
   434  	// Get body from one version ago in json format
   435  	output = run.MustExec(t, fmt.Sprintf("qri get body %s", ref))
   436  	expect = prevBodyJSON
   437  	if diff := cmp.Diff(expect, output); diff != "" {
   438  		t.Errorf("unexpected (-want +got):\n%s", diff)
   439  	}
   440  
   441  }
   442  
   443  func TestGetDatasetUsingDscache(t *testing.T) {
   444  	t.Skip("TODO(dustmop): Need a way to enable Dscache without the Param field")
   445  
   446  	run := NewTestRunner(t, "test_peer_get", "get_dataset_head")
   447  	defer run.Delete()
   448  
   449  	// Save two versions, using dscache.
   450  	got := run.MustExecCombinedOutErr(t, "qri save --use-dscache --body=testdata/movies/body_ten.csv me/my_ds")
   451  	ref := parseRefFromSave(got)
   452  	run.MustExec(t, "qri save --use-dscache --body=testdata/movies/body_twenty.csv me/my_ds")
   453  
   454  	// Get head.
   455  	output := run.MustExec(t, "qri get me/my_ds")
   456  	expect := dstest.Template(t, currHeadRepo, currHeadRepoData)
   457  	if diff := cmp.Diff(expect, output); diff != "" {
   458  		t.Errorf("unexpected (-want +got):\n%s", diff)
   459  	}
   460  
   461  	// Get one version ago.
   462  	output = run.MustExec(t, fmt.Sprintf("qri get %s", ref))
   463  	expect = dstest.Template(t, prevHeadRepo, prevHeadRepoData)
   464  	if diff := cmp.Diff(expect, output); diff != "" {
   465  		t.Errorf("unexpected (-want +got):\n%s", diff)
   466  	}
   467  
   468  	// Get body from current commit.
   469  	output = run.MustExec(t, "qri get body me/my_ds")
   470  	expect = currBodyRepo
   471  	if diff := cmp.Diff(expect, output); diff != "" {
   472  		t.Errorf("unexpected (-want +got):\n%s", diff)
   473  	}
   474  
   475  	// Get body from one version ago.
   476  	output = run.MustExec(t, fmt.Sprintf("qri get body %s", ref))
   477  	expect = prevBodyRepo
   478  	if diff := cmp.Diff(expect, output); diff != "" {
   479  		t.Errorf("unexpected (-want +got):\n%s", diff)
   480  	}
   481  }
   482  
   483  func TestGetRemoteDataset(t *testing.T) {
   484  	run := NewTestRunnerWithMockRemoteClient(t, "test_get_remote_dataset", "get_remote_dataset")
   485  	defer run.Delete()
   486  
   487  	expect := "cannot use '--offline' and '--remote' flags together"
   488  	err := run.ExecCommand("qri get --remote=registry --offline other_peer/their_dataset")
   489  	if err == nil {
   490  		t.Fatal("expected to get an error, did not get one")
   491  	}
   492  	if expect != err.Error() {
   493  		t.Errorf("response mismatch\nwant: %q\n got: %q", expect, err)
   494  	}
   495  
   496  	expect = "reference not found"
   497  	err = run.ExecCommand("qri get --offline other_peer/their_dataset")
   498  	if err == nil {
   499  		t.Fatal("expected to get an error, did not get one")
   500  	}
   501  	if expect != err.Error() {
   502  		t.Errorf("response mismatch\nwant: %q\n got: %q", expect, err)
   503  	}
   504  
   505  	// mock remote datasets have empty bodies
   506  	expect = dstest.Template(t, `body: {}
   507  bodyPath: {{ .bodyPath }}
   508  commit:
   509    message: created dataset
   510    path: {{ .commitPath }}
   511    qri: cm:0
   512    signature: {{ .signature }}
   513    timestamp: "2001-01-01T01:01:01.000000001Z"
   514    title: created dataset
   515  id: {{ .id }}
   516  name: their_dataset
   517  path: {{ .path }}
   518  peername: other_peer
   519  qri: ds:0
   520  stats: {{ .statsPath }}
   521  structure:
   522    checksum: {{ .bodyPath }}
   523    depth: 1
   524    format: json
   525    length: 2
   526    path: {{ .structurePath }}
   527    qri: st:0
   528    schema:
   529      type: object
   530  
   531  `, map[string]string{
   532  		"id":            "zgseugtra4h7ekpzfuczupudzyrfrhafx3ucb35kbafb37p2575q",
   533  		"bodyPath":      "/ipfs/QmbJWAESqCsf4RFCqEY7jecCashj8usXiyDNfKtZCwwzGb",
   534  		"commitPath":    "/ipfs/QmTTPd47BD4EGpCpuvRwTRqDRF84iAuJmfUUGcfEBuF7he",
   535  		"signature":     "gySMr/FiT+kz0X2ODXCE5APx/BvPvalw4xlbS8TtSWssEoHlAOdrUNKUfU7j6rjyq7sFJ7hrbIVOn87fx+7arYCvrvikRawd2anzIvIruxfBymS6A0HtAGAOEAvpn3XbDykEjqaomTXS1CyR6wQkwNEgbELCIqwda9UV3ulhUtHMrAyMxvnq3NG6J9wyFB13u133aDVEojJ82mEF5DBFB+VBVbw90S4b/5AxLEUFSt/BCtE1O0lKYCt2x0HK+1fhl85oe3fpqLhLk96qCAR/Ngv4bt0E9NjGi2ltuji8gaDICKe5KRaSXjXlMkwbUq6sXEKgqzfxHXoIAUZnZNwnmg==",
   536  		"path":          "/ipfs/QmUv37uYowTAYx2VTsdBcpgHoqRQppQyrnf5yEZcAwcp9P",
   537  		"statsPath":     "/ipfs/QmQQkQF2KNBZfFiX33jJ9hu6ivfoHrtgcwMRAezS4dcA7c",
   538  		"structurePath": "/ipfs/QmWoYVZWDdiNauzeP171hKSdo3p2bFaqDcW6cppb9QugUE",
   539  	})
   540  	got := run.MustExec(t, "qri get --remote=registry other_peer/their_dataset")
   541  	if diff := cmp.Diff(expect, got); diff != "" {
   542  		t.Errorf("repsonse mismatch (-want +got):\n%s", diff)
   543  	}
   544  }