diff --git a/rest/attachment_test.go b/rest/attachment_test.go index 964315ac47..a485cd9f30 100644 --- a/rest/attachment_test.go +++ b/rest/attachment_test.go @@ -2431,10 +2431,10 @@ func TestAttachmentWithErroneousRevPos(t *testing.T) { btcRunner.saveAttachment(btc.id, base64.StdEncoding.EncodeToString([]byte("goodbye cruel world"))) // Put doc with an erroneous revpos 1 but with a different digest, referring to the above attachment - updatedVersion, err := btcRunner.PushRevWithHistory(btc.id, docID, &version, []byte(`{"_attachments": {"hello.txt": {"revpos":1,"stub":true,"length": 19,"digest":"sha1-l+N7VpXGnoxMm8xfvtWPbz2YvDc="}}}`), 1, 0) - require.NoError(t, err) + updatedVersion := btcRunner.AddRev(btc.id, docID, &version, []byte(`{"_attachments": {"hello.txt": {"revpos":1,"stub":true,"length": 19,"digest":"sha1-l+N7VpXGnoxMm8xfvtWPbz2YvDc="}}}`)) - rt.WaitForVersion(docID, *updatedVersion) + btcRunner.StartPush(btc.id) + rt.WaitForVersion(docID, updatedVersion) // Get the attachment and ensure the data is updated resp := btc.rt.SendAdminRequest(http.MethodGet, "/{{.keyspace}}/doc/hello.txt", "") diff --git a/rest/blip_api_delta_sync_test.go b/rest/blip_api_delta_sync_test.go index 0b5421d132..14ef981e37 100644 --- a/rest/blip_api_delta_sync_test.go +++ b/rest/blip_api_delta_sync_test.go @@ -811,7 +811,6 @@ func TestBlipDeltaSyncPush(t *testing.T) { client.ClientDeltas = true btcRunner.StartPull(client.id) - btcRunner.StartPush(client.id) // create doc1 rev 1-0335a345b6ffed05707ccc4cbc1b67f4 version := rt.PutDoc(docID, `{"greetings": [{"hello": "world!"}, {"hi": "alice"}]}`) @@ -820,6 +819,7 @@ func TestBlipDeltaSyncPush(t *testing.T) { assert.Equal(t, `{"greetings":[{"hello":"world!"},{"hi":"alice"}]}`, string(data)) // create doc1 rev 2-abc on client newRev := btcRunner.AddRev(client.id, docID, &version, []byte(`{"greetings":[{"hello":"world!"},{"hi":"alice"},{"howdy":"bob"}]}`)) + btcRunner.StartPushWithOpts(client.id, BlipTesterPushOptions{Continuous: false}) // Check EE is delta, and CE is full-body replication msg := client.waitForReplicationMessage(collection, 2) @@ -868,18 +868,31 @@ func TestBlipDeltaSyncPush(t *testing.T) { if rt.GetDatabase().DbStats.DeltaSync() != nil { deltaPushDocCountStart = rt.GetDatabase().DbStats.DeltaSync().DeltaPushDocCount.Value() } - - _, err := btcRunner.PushUnsolicitedRev(client.id, docID, &deletedVersion, []byte(`{"undelete":true}`)) - - if base.IsEnterpriseEdition() { + revRequest := blip.NewRequest() + revRequest.SetProfile(db.MessageRev) + revRequest.Properties[db.RevMessageID] = docID + revRequest.Properties[db.RevMessageRev] = "4-abc" + revRequest.Properties[db.RevMessageHistory] = deletedVersion.RevID + revRequest.SetBody([]byte(`{"undelete": "true"}`)) + useDeltas := base.IsEnterpriseEdition() + if useDeltas { + revRequest.Properties[db.RevMessageDeltaSrc] = deletedVersion.RevID + } + btcRunner.SingleCollection(client.id).sendPushMsg(revRequest) + revResp := revRequest.Response() + if useDeltas { + body, err := revResp.Body() + require.NoError(t, err) // Now make the client push up a delta that has the parent of the tombstone. - // This is not a valid scenario, and is actively prevented on the CBL side. - assert.Error(t, err) - assert.Contains(t, err.Error(), "Can't use delta. Found tombstone for doc") + // This is not a valid scenario, and is actively prevented on the CBL side. Assert Sync Gateway will catch this error. + require.Equal(t, blip.ErrorType, revResp.Type()) + require.Equal(t, `422`, revResp.Properties["Error-Code"], "Did not find correct output for %s", body) + require.Contains(t, string(body), "Can't use delta. Found tombstone") } else { // Pushing a full body revision on top of a tombstone is valid. // CBL clients should fall back to this. The test client doesn't. - assert.NoError(t, err) + require.NotContains(t, revResp.Properties, "Error-Domain") + require.NotContains(t, revResp.Properties, "Error-Code") } var deltaPushDocCountEnd int64 diff --git a/rest/blip_client_test.go b/rest/blip_client_test.go index 11f2f63131..54a3023105 100644 --- a/rest/blip_client_test.go +++ b/rest/blip_client_test.go @@ -1361,96 +1361,6 @@ func (btcc *BlipTesterCollectionClient) AddRev(docID string, parentVersion *DocV return newRev.version } -// PushUnsolicitedRev creates a revision on the client, and immediately sends a changes request for it. This is only intended for use when there is no push replication running. -func (btcc *BlipTesterCollectionClient) PushUnsolicitedRev(docID string, parentRev *DocVersion, body []byte) (version *DocVersion, err error) { - return btcc.PushRevWithHistory(docID, parentRev, body, 1, 0) -} - -// PushRevWithHistory creates a revision on the client with history, and immediately sends a changes request for it. -func (btcc *BlipTesterCollectionClient) PushRevWithHistory(docID string, parentVersion *DocVersion, body []byte, revCount, prunedRevCount int) (version *DocVersion, err error) { - ctx := base.DatabaseLogCtx(base.TestCtx(btcc.parent.rt.TB()), btcc.parent.rt.GetDatabase().Name, nil) - parentRevGen := parentVersion.RevIDGeneration() - revGen := parentRevGen + revCount + prunedRevCount - - var revisionHistory []string - for i := revGen - 1; i > parentRevGen; i-- { - rev := fmt.Sprintf("%d-%s", i, "abc") - revisionHistory = append(revisionHistory, rev) - } - - // Inline attachment processing - body = btcc.ProcessInlineAttachments(body, revGen) - - var parentDocBody []byte - if parentVersion != nil { - doc, ok := btcc.getClientDoc(docID) - if !ok { - return nil, fmt.Errorf("doc %s not found in client", docID) - } - doc.lock.RLock() - parentDocBody = doc._revisionsBySeq[doc._seqsByVersions[*parentVersion]].body - doc.lock.RUnlock() - } - - newRevID := fmt.Sprintf("%d-%s", revGen, "abc") - newRev := btcc.upsertDoc(docID, parentVersion, body) - - // send a proposeChanges message with the single rev we just created on the client - proposeChangesRequest := blip.NewRequest() - proposeChangesRequest.SetProfile(db.MessageProposeChanges) - var serverVersionComponent string - if parentVersion != nil { - serverVersionComponent = fmt.Sprintf(`,"%s"`, parentVersion.RevID) - } - proposeChangesRequest.SetBody([]byte(fmt.Sprintf(`[["%s","%s"%s]]`, docID, newRevID, serverVersionComponent))) - - btcc.addCollectionProperty(proposeChangesRequest) - - btcc.sendPushMsg(proposeChangesRequest) - - proposeChangesResponse := proposeChangesRequest.Response() - rspBody, err := proposeChangesResponse.Body() - require.NoError(btcc.TB(), err) - require.NotContains(btcc.TB(), proposeChangesResponse.Properties, "Error-Domain", "unexpected error response from proposeChanges: %v, %s", proposeChangesResponse, rspBody) - require.NotContains(btcc.TB(), proposeChangesResponse.Properties, "Error-Code", "unexpected error response from proposeChanges: %v, %s", proposeChangesResponse, rspBody) - require.Equal(btcc.TB(), "[]", string(rspBody)) - - // send msg rev with new doc - revRequest := blip.NewRequest() - revRequest.SetProfile(db.MessageRev) - revRequest.Properties[db.RevMessageID] = docID - revRequest.Properties[db.RevMessageRev] = newRevID - revRequest.Properties[db.RevMessageHistory] = strings.Join(revisionHistory, ",") - - btcc.addCollectionProperty(revRequest) - if btcc.parent.ClientDeltas && proposeChangesResponse.Properties[db.ProposeChangesResponseDeltas] == "true" && parentVersion != nil { - base.DebugfCtx(ctx, base.KeySync, "Sending deltas from test client from parent %v", parentVersion) - var parentDocJSON, newDocJSON db.Body - require.NoError(btcc.TB(), parentDocJSON.Unmarshal(parentDocBody)) - require.NoError(btcc.TB(), newDocJSON.Unmarshal(body)) - delta, err := base.Diff(parentDocJSON, newDocJSON) - require.NoError(btcc.TB(), err) - revRequest.Properties[db.RevMessageDeltaSrc] = parentVersion.RevID - body = delta - } else { - base.DebugfCtx(ctx, base.KeySync, "Not sending deltas from test client") - } - - revRequest.SetBody(body) - - btcc.sendPushMsg(revRequest) - - revResponse := revRequest.Response() - rspBody, err = revResponse.Body() - require.NoError(btcc.TB(), err) - if revResponse.Type() == blip.ErrorType { - return nil, fmt.Errorf("error %s %s from revResponse: %s", revResponse.Properties["Error-Domain"], revResponse.Properties["Error-Code"], rspBody) - } - - btcc.updateLastReplicatedRev(docID, newRev.version) - return &newRev.version, nil -} - func (btcc *BlipTesterCollectionClient) ProcessInlineAttachments(inputBody []byte, revGen int) (outputBody []byte) { if !bytes.Contains(inputBody, []byte(db.BodyAttachments)) { return inputBody @@ -1663,10 +1573,6 @@ func (btcRunner *BlipTestClientRunner) AddRev(clientID uint32, docID string, ver return btcRunner.SingleCollection(clientID).AddRev(docID, version, body) } -func (btcRunner *BlipTestClientRunner) PushUnsolicitedRev(clientID uint32, docID string, parentVersion *DocVersion, body []byte) (*DocVersion, error) { - return btcRunner.SingleCollection(clientID).PushUnsolicitedRev(docID, parentVersion, body) -} - func (btcRunner *BlipTestClientRunner) StartPullSince(clientID uint32, options BlipTesterPullOptions) { btcRunner.SingleCollection(clientID).StartPullSince(options) } @@ -1680,11 +1586,6 @@ func (btcRunner *BlipTestClientRunner) saveAttachment(clientID uint32, attachmen return btcRunner.SingleCollection(clientID).saveAttachment(attachmentData) } -// PushRevWithHistory creates a revision on the client with history, and immediately sends a changes request for it. -func (btcRunner *BlipTestClientRunner) PushRevWithHistory(clientID uint32, docID string, parentVersion *DocVersion, body []byte, revCount, prunedRevCount int) (*DocVersion, error) { - return btcRunner.SingleCollection(clientID).PushRevWithHistory(docID, parentVersion, body, revCount, prunedRevCount) -} - // UnsubPullChanges will send an UnsubChanges message to the server to stop the pull replication. Fails test harness if Sync Gateway responds with an error. func (btcRunner *BlipTestClientRunner) UnsubPullChanges(clientID uint32) { btcRunner.SingleCollection(clientID).UnsubPullChanges()