(t *testing.T)
| 1677 | } |
| 1678 | |
| 1679 | func TestDocUpdateCorruptSequence(t *testing.T) { |
| 1680 | if !base.TestUseXattrs() { |
| 1681 | t.Skip("This test only works with XATTRS enabled") |
| 1682 | } |
| 1683 | base.SetUpTestLogging(t, base.LevelInfo, base.KeyCache, base.KeyChanges, base.KeyCRUD, base.KeyDCP) |
| 1684 | |
| 1685 | db, ctx := SetupTestDBWithOptions(t, DatabaseContextOptions{}) |
| 1686 | defer db.Close(ctx) |
| 1687 | |
| 1688 | // create a sequence much higher than _syc:seqs value |
| 1689 | const corruptSequence = MaxSequencesToRelease + 1000 |
| 1690 | |
| 1691 | collection, ctx := GetSingleDatabaseCollectionWithUser(ctx, t, db) |
| 1692 | rev, doc, err := collection.Put(ctx, "doc1", Body{"foo": "bar"}) |
| 1693 | require.NoError(t, err) |
| 1694 | docRev := doc.RevID |
| 1695 | t.Logf("doc sequence: %d", doc.Sequence) |
| 1696 | |
| 1697 | // but we can fiddle with the sequence in the metadata of the doc write to simulate a doc from a different cluster (with a higher sequence) |
| 1698 | _, xattrs, _, err := collection.dataStore.GetWithXattrs(ctx, "doc1", []string{base.SyncXattrName}) |
| 1699 | require.NoError(t, err) |
| 1700 | var newSyncData map[string]interface{} |
| 1701 | err = json.Unmarshal(xattrs[base.SyncXattrName], &newSyncData) |
| 1702 | require.NoError(t, err) |
| 1703 | newSyncData["sequence"] = corruptSequence |
| 1704 | _, err = collection.dataStore.UpdateXattrs(ctx, doc.ID, 0, doc.Cas, map[string][]byte{base.SyncXattrName: base.MustJSONMarshal(t, newSyncData)}, DefaultMutateInOpts()) |
| 1705 | require.NoError(t, err) |
| 1706 | |
| 1707 | _, _, err = collection.Put(ctx, "doc1", Body{"foo": "buzz", BodyRev: rev}) |
| 1708 | require.Error(t, err) |
| 1709 | require.ErrorIs(t, err, base.ErrMaxSequenceReleasedExceeded) |
| 1710 | |
| 1711 | // assert update to doc was cancelled thus doc1 is its original version |
| 1712 | doc, err = collection.GetDocument(ctx, "doc1", DocUnmarshalAll) |
| 1713 | require.NoError(t, err) |
| 1714 | assert.Equal(t, uint64(corruptSequence), doc.Sequence) |
| 1715 | assert.Equal(t, docRev, doc.RevID) |
| 1716 | |
| 1717 | base.RequireWaitForStat(t, func() int64 { |
| 1718 | return db.DbStats.Database().CorruptSequenceCount.Value() |
| 1719 | }, 1) |
| 1720 | } |
| 1721 | |
| 1722 | func TestPutResurrection(t *testing.T) { |
| 1723 | base.SetUpTestLogging(t, base.LevelDebug, base.KeyAll) |
nothing calls this directly
no test coverage detected