public void TestAttachments() { const string testAttachmentName = "test_attachment"; var attachments = database.Attachments; Assert.AreEqual(0, attachments.Count()); Assert.AreEqual(0, attachments.AllKeys().Count()); var attach1 = Encoding.UTF8.GetBytes("This is the body of attach1"); var props = new Dictionary <string, object> { { "foo", 1 }, { "bar", false }, { "_attachments", CreateAttachmentsDict(attach1, testAttachmentName, "text/plain", false) } }; Status status = new Status(); RevisionInternal rev1 = database.PutRevision(new RevisionInternal(props), null, false, status); Assert.AreEqual(StatusCode.Created, status.GetCode()); var att = database.GetAttachmentForRevision(rev1, testAttachmentName, status); Assert.IsNotNull(att, "Couldn't get attachment: Status {0}", status.GetCode()); Assert.AreEqual(attach1, att.Content); Assert.AreEqual("text/plain", att.ContentType); Assert.AreEqual(AttachmentEncoding.None, att.Encoding); var itemDict = new Dictionary <string, object> { { "content_type", "text/plain" }, { "digest", "sha1-gOHUOBmIMoDCrMuGyaLWzf1hQTE=" }, { "length", 27 }, { "stub", true }, { "revpos", 1 } }; var attachmentDict = new Dictionary <string, object> { { testAttachmentName, itemDict } }; var gotRev1 = database.GetDocumentWithIDAndRev(rev1.GetDocId(), rev1.GetRevId(), DocumentContentOptions.None); AssertDictionariesAreEqual(attachmentDict, gotRev1.GetAttachments()); itemDict.Remove("stub"); itemDict["data"] = Convert.ToBase64String(attach1); gotRev1 = database.GetDocumentWithIDAndRev(rev1.GetDocId(), rev1.GetRevId(), DocumentContentOptions.IncludeAttachments); var expandedRev = gotRev1.CopyWithDocID(rev1.GetDocId(), rev1.GetRevId()); Assert.IsTrue(database.ExpandAttachments(expandedRev, 0, false, true, status)); AssertDictionariesAreEqual(attachmentDict, expandedRev.GetAttachments()); // Add a second revision that doesn't update the attachment: props = new Dictionary <string, object> { { "_id", rev1.GetDocId() }, { "foo", 2 }, { "bazz", false }, { "_attachments", CreateAttachmentsStub(testAttachmentName) } }; var rev2 = database.PutRevision(new RevisionInternal(props), rev1.GetRevId(), status); Assert.AreEqual(StatusCode.Created, status.GetCode()); // Add a third revision of the same document: var attach2 = Encoding.UTF8.GetBytes("<html>And this is attach2</html>"); props = new Dictionary <string, object> { { "_id", rev2.GetDocId() }, { "foo", 2 }, { "bazz", false }, { "_attachments", CreateAttachmentsDict(attach2, testAttachmentName, "text/html", false) } }; var rev3 = database.PutRevision(new RevisionInternal(props), rev2.GetRevId(), status); Assert.AreEqual(StatusCode.Created, status.GetCode()); // Check the second revision's attachment att = database.GetAttachmentForRevision(rev2, testAttachmentName, status); Assert.IsNotNull(att, "Couldn't get attachment: Status {0}", status.GetCode()); Assert.AreEqual(attach1, att.Content); Assert.AreEqual("text/plain", att.ContentType); Assert.AreEqual(AttachmentEncoding.None, att.Encoding); expandedRev = rev2.CopyWithDocID(rev2.GetDocId(), rev2.GetRevId()); Assert.IsTrue(database.ExpandAttachments(expandedRev, 2, false, true, status)); AssertDictionariesAreEqual(new Dictionary <string, object> { { testAttachmentName, new Dictionary <string, object> { { "stub", true }, { "revpos", 1 } } } }, expandedRev.GetAttachments()); // Check the 3rd revision's attachment: att = database.GetAttachmentForRevision(rev3, testAttachmentName, status); Assert.IsNotNull(att, "Couldn't get attachment: Status {0}", status.GetCode()); Assert.AreEqual(attach2, att.Content); Assert.AreEqual("text/html", att.ContentType); Assert.AreEqual(AttachmentEncoding.None, att.Encoding); expandedRev = rev3.CopyWithDocID(rev3.GetDocId(), rev3.GetRevId()); Assert.IsTrue(database.ExpandAttachments(expandedRev, 2, false, true, status)); attachmentDict = new Dictionary <string, object> { { testAttachmentName, new Dictionary <string, object> { { "content_type", "text/html" }, { "data", "PGh0bWw+QW5kIHRoaXMgaXMgYXR0YWNoMjwvaHRtbD4=" }, { "digest", "sha1-s14XRTXlwvzYfjo1t1u0rjB+ZUA=" }, { "length", 32 }, { "revpos", 3 } } } }; AssertDictionariesAreEqual(attachmentDict, expandedRev.GetAttachments()); // Examine the attachment store: Assert.AreEqual(2, attachments.Count()); Assert.AreEqual(new HashSet <BlobKey> { BlobStore.KeyForBlob(attach1), BlobStore.KeyForBlob(attach2) }, attachments.AllKeys()); database.Compact(); Assert.AreEqual(1, attachments.Count()); Assert.AreEqual(new HashSet <BlobKey> { BlobStore.KeyForBlob(attach2) }, attachments.AllKeys()); }
/// <exception cref="System.Exception"></exception> public virtual void TestAttachments() { string testAttachmentName = "test_attachment"; BlobStore attachments = database.GetAttachments(); NUnit.Framework.Assert.AreEqual(0, attachments.Count()); NUnit.Framework.Assert.AreEqual(new HashSet <object>(), attachments.AllKeys()); Status status = new Status(); IDictionary <string, object> rev1Properties = new Dictionary <string, object>(); rev1Properties.Put("foo", 1); rev1Properties.Put("bar", false); RevisionInternal rev1 = database.PutRevision(new RevisionInternal(rev1Properties, database), null, false, status); NUnit.Framework.Assert.AreEqual(Status.Created, status.GetCode()); byte[] attach1 = Sharpen.Runtime.GetBytesForString("This is the body of attach1"); database.InsertAttachmentForSequenceWithNameAndType(new ByteArrayInputStream(attach1 ), rev1.GetSequence(), testAttachmentName, "text/plain", rev1.GetGeneration()); NUnit.Framework.Assert.AreEqual(Status.Created, status.GetCode()); Attachment attachment = database.GetAttachmentForSequence(rev1.GetSequence(), testAttachmentName ); NUnit.Framework.Assert.AreEqual("text/plain", attachment.GetContentType()); byte[] data = IOUtils.ToByteArray(attachment.GetContent()); NUnit.Framework.Assert.IsTrue(Arrays.Equals(attach1, data)); IDictionary <string, object> innerDict = new Dictionary <string, object>(); innerDict.Put("content_type", "text/plain"); innerDict.Put("digest", "sha1-gOHUOBmIMoDCrMuGyaLWzf1hQTE="); innerDict.Put("length", 27); innerDict.Put("stub", true); innerDict.Put("revpos", 1); IDictionary <string, object> attachmentDict = new Dictionary <string, object>(); attachmentDict.Put(testAttachmentName, innerDict); IDictionary <string, object> attachmentDictForSequence = database.GetAttachmentsDictForSequenceWithContent (rev1.GetSequence(), EnumSet.NoneOf <Database.TDContentOptions>()); NUnit.Framework.Assert.AreEqual(attachmentDict, attachmentDictForSequence); RevisionInternal gotRev1 = database.GetDocumentWithIDAndRev(rev1.GetDocId(), rev1 .GetRevId(), EnumSet.NoneOf <Database.TDContentOptions>()); IDictionary <string, object> gotAttachmentDict = (IDictionary <string, object>)gotRev1 .GetProperties().Get("_attachments"); NUnit.Framework.Assert.AreEqual(attachmentDict, gotAttachmentDict); // Check the attachment dict, with attachments included: Sharpen.Collections.Remove(innerDict, "stub"); innerDict.Put("data", Base64.EncodeBytes(attach1)); attachmentDictForSequence = database.GetAttachmentsDictForSequenceWithContent(rev1 .GetSequence(), EnumSet.Of(Database.TDContentOptions.TDIncludeAttachments)); NUnit.Framework.Assert.AreEqual(attachmentDict, attachmentDictForSequence); gotRev1 = database.GetDocumentWithIDAndRev(rev1.GetDocId(), rev1.GetRevId(), EnumSet .Of(Database.TDContentOptions.TDIncludeAttachments)); gotAttachmentDict = (IDictionary <string, object>)gotRev1.GetProperties().Get("_attachments" ); NUnit.Framework.Assert.AreEqual(attachmentDict, gotAttachmentDict); // Add a second revision that doesn't update the attachment: IDictionary <string, object> rev2Properties = new Dictionary <string, object>(); rev2Properties.Put("_id", rev1.GetDocId()); rev2Properties.Put("foo", 2); rev2Properties.Put("bazz", false); RevisionInternal rev2 = database.PutRevision(new RevisionInternal(rev2Properties, database), rev1.GetRevId(), false, status); NUnit.Framework.Assert.AreEqual(Status.Created, status.GetCode()); database.CopyAttachmentNamedFromSequenceToSequence(testAttachmentName, rev1.GetSequence (), rev2.GetSequence()); // Add a third revision of the same document: IDictionary <string, object> rev3Properties = new Dictionary <string, object>(); rev3Properties.Put("_id", rev2.GetDocId()); rev3Properties.Put("foo", 2); rev3Properties.Put("bazz", false); RevisionInternal rev3 = database.PutRevision(new RevisionInternal(rev3Properties, database), rev2.GetRevId(), false, status); NUnit.Framework.Assert.AreEqual(Status.Created, status.GetCode()); byte[] attach2 = Sharpen.Runtime.GetBytesForString("<html>And this is attach2</html>" ); database.InsertAttachmentForSequenceWithNameAndType(new ByteArrayInputStream(attach2 ), rev3.GetSequence(), testAttachmentName, "text/html", rev2.GetGeneration()); // Check the 2nd revision's attachment: Attachment attachment2 = database.GetAttachmentForSequence(rev2.GetSequence(), testAttachmentName ); NUnit.Framework.Assert.AreEqual("text/plain", attachment2.GetContentType()); data = IOUtils.ToByteArray(attachment2.GetContent()); NUnit.Framework.Assert.IsTrue(Arrays.Equals(attach1, data)); // Check the 3rd revision's attachment: Attachment attachment3 = database.GetAttachmentForSequence(rev3.GetSequence(), testAttachmentName ); NUnit.Framework.Assert.AreEqual("text/html", attachment3.GetContentType()); data = IOUtils.ToByteArray(attachment3.GetContent()); NUnit.Framework.Assert.IsTrue(Arrays.Equals(attach2, data)); // Examine the attachment store: NUnit.Framework.Assert.AreEqual(2, attachments.Count()); ICollection <BlobKey> expected = new HashSet <BlobKey>(); expected.AddItem(BlobStore.KeyForBlob(attach1)); expected.AddItem(BlobStore.KeyForBlob(attach2)); NUnit.Framework.Assert.AreEqual(expected, attachments.AllKeys()); database.Compact(); // This clears the body of the first revision NUnit.Framework.Assert.AreEqual(1, attachments.Count()); ICollection <BlobKey> expected2 = new HashSet <BlobKey>(); expected2.AddItem(BlobStore.KeyForBlob(attach2)); NUnit.Framework.Assert.AreEqual(expected2, attachments.AllKeys()); }
public void TestAttachments() { var testAttachmentName = "test_attachment"; var attachments = database.Attachments; Assert.AreEqual(0, attachments.Count()); Assert.AreEqual(0, attachments.AllKeys().Count()); var rev1Properties = new Dictionary <string, object>(); rev1Properties["foo"] = 1; rev1Properties["bar"] = false; var status = new Status(); var rev1 = database.PutRevision( new RevisionInternal(rev1Properties), null, false, status); Assert.AreEqual(StatusCode.Created, status.GetCode()); var attach1 = Encoding.UTF8.GetBytes("This is the body of attach1"); database.InsertAttachmentForSequenceWithNameAndType( new ByteArrayInputStream(attach1), rev1.GetSequence(), testAttachmentName, "text/plain", rev1.GetGeneration()); //We must set the no_attachments column for the rev to false, as we are using an internal //private API call above (database.insertAttachmentForSequenceWithNameAndType) which does //not set the no_attachments column on revs table try { var args = new ContentValues(); args.Put("no_attachments", false); database.StorageEngine.Update( "revs", args, "sequence=?", new[] { rev1.GetSequence().ToString() } ); } catch (SQLException e) { Log.E(Tag, "Error setting rev1 no_attachments to false", e); throw new CouchbaseLiteException(StatusCode.InternalServerError); } var attachment = database.GetAttachmentForSequence( rev1.GetSequence(), testAttachmentName ); Assert.AreEqual("text/plain", attachment.ContentType); var data = attachment.Content.ToArray(); Assert.IsTrue(Arrays.Equals(attach1, data)); attachment.Dispose(); var innerDict = new Dictionary <string, object>(); innerDict["content_type"] = "text/plain"; innerDict["digest"] = "sha1-gOHUOBmIMoDCrMuGyaLWzf1hQTE="; innerDict["length"] = 27; innerDict["stub"] = true; innerDict["revpos"] = 1; var attachmentDict = new Dictionary <string, object>(); attachmentDict[testAttachmentName] = innerDict; var attachmentDictForSequence = database.GetAttachmentsDictForSequenceWithContent(rev1.GetSequence(), DocumentContentOptions.None); Assert.AreEqual(new SortedDictionary <string, object>(attachmentDict), new SortedDictionary <string, object>(attachmentDictForSequence));//Assert.AreEqual(1, attachmentDictForSequence.Count); var gotRev1 = database.GetDocumentWithIDAndRev(rev1.GetDocId(), rev1.GetRevId(), DocumentContentOptions.IncludeAttachments); var gotAttachmentDict = gotRev1.GetProperties() .Get("_attachments") .AsDictionary <string, object>(); Assert.AreEqual(attachmentDict.Select(kvp => kvp.Key).OrderBy(k => k), gotAttachmentDict.Select(kvp => kvp.Key).OrderBy(k => k)); // Check the attachment dict, with attachments included: innerDict.Remove("stub"); innerDict.Put("data", Convert.ToBase64String(attach1)); attachmentDictForSequence = database.GetAttachmentsDictForSequenceWithContent( rev1.GetSequence(), DocumentContentOptions.IncludeAttachments); Assert.AreEqual(new SortedDictionary <string, object>(attachmentDict[testAttachmentName].AsDictionary <string, object>()), new SortedDictionary <string, object>(attachmentDictForSequence[testAttachmentName].AsDictionary <string, object>())); gotRev1 = database.GetDocumentWithIDAndRev( rev1.GetDocId(), rev1.GetRevId(), DocumentContentOptions.IncludeAttachments); gotAttachmentDict = gotRev1.GetProperties() .Get("_attachments") .AsDictionary <string, object>() .Get(testAttachmentName) .AsDictionary <string, object>(); Assert.AreEqual(innerDict.Select(kvp => kvp.Key).OrderBy(k => k), gotAttachmentDict.Select(kvp => kvp.Key).OrderBy(k => k)); // Add a second revision that doesn't update the attachment: database.BeginTransaction(); var rev2Properties = new Dictionary <string, object>(); rev2Properties.Put("_id", rev1.GetDocId()); rev2Properties["foo"] = 2; rev2Properties["bazz"] = false; var rev2 = database.PutRevision(new RevisionInternal(rev2Properties), rev1.GetRevId(), false, status); Assert.AreEqual(StatusCode.Created, status.GetCode()); database.CopyAttachmentNamedFromSequenceToSequence( testAttachmentName, rev1.GetSequence(), rev2.GetSequence()); database.EndTransaction(true); // Add a third revision of the same document: var rev3Properties = new Dictionary <string, object>(); rev3Properties.Put("_id", rev2.GetDocId()); rev3Properties["foo"] = 2; rev3Properties["bazz"] = false; database.BeginTransaction(); var rev3 = database.PutRevision(new RevisionInternal( rev3Properties), rev2.GetRevId(), false, status); Assert.AreEqual(StatusCode.Created, status.GetCode()); var attach2 = Encoding.UTF8.GetBytes("<html>And this is attach2</html>"); database.InsertAttachmentForSequenceWithNameAndType( new ByteArrayInputStream(attach2), rev3.GetSequence(), testAttachmentName, "text/html", rev2.GetGeneration()); database.EndTransaction(true); // Check the 2nd revision's attachment: var attachment2 = database.GetAttachmentForSequence(rev2.GetSequence(), testAttachmentName); Assert.AreEqual("text/plain", attachment2.ContentType); data = attachment2.Content.ToArray(); Assert.IsTrue(Arrays.Equals(attach1, data)); attachment2.Dispose(); // Check the 3rd revision's attachment: var attachment3 = database.GetAttachmentForSequence(rev3.GetSequence(), testAttachmentName); Assert.AreEqual("text/html", attachment3.ContentType); data = attachment3.Content.ToArray(); Assert.IsTrue(Arrays.Equals(attach2, data)); var attachmentDictForRev3 = database.GetAttachmentsDictForSequenceWithContent(rev3.GetSequence(), DocumentContentOptions.None) .Get(testAttachmentName) .AsDictionary <string, object>(); if (attachmentDictForRev3.ContainsKey("follows")) { if (((bool)attachmentDictForRev3.Get("follows")) == true) { throw new RuntimeException("Did not expected attachment dict 'follows' key to be true" ); } else { throw new RuntimeException("Did not expected attachment dict to have 'follows' key" ); } } attachment3.Dispose(); // Examine the attachment store: Assert.AreEqual(2, attachments.Count()); var expected = new HashSet <BlobKey>(); expected.AddItem(BlobStore.KeyForBlob(attach1)); expected.AddItem(BlobStore.KeyForBlob(attach2)); Assert.AreEqual(expected.Count, attachments.AllKeys().Count()); foreach (var key in attachments.AllKeys()) { Assert.IsTrue(expected.Contains(key)); } database.Compact(); // This clears the body of the first revision Assert.AreEqual(1, attachments.Count()); var expected2 = new HashSet <BlobKey>(); expected2.AddItem(BlobStore.KeyForBlob(attach2)); Assert.AreEqual(expected2.Count, attachments.AllKeys().Count()); foreach (var key in attachments.AllKeys()) { Assert.IsTrue(expected2.Contains(key)); } }
/// <exception cref="System.Exception"></exception> public virtual void TestAttachments() { string testAttachmentName = "test_attachment"; BlobStore attachments = database.GetAttachments(); NUnit.Framework.Assert.AreEqual(0, attachments.Count()); NUnit.Framework.Assert.AreEqual(new HashSet <object>(), attachments.AllKeys()); Status status = new Status(); IDictionary <string, object> rev1Properties = new Dictionary <string, object>(); rev1Properties.Put("foo", 1); rev1Properties.Put("bar", false); RevisionInternal rev1 = database.PutRevision(new RevisionInternal(rev1Properties, database), null, false, status); NUnit.Framework.Assert.AreEqual(Status.Created, status.GetCode()); byte[] attach1 = Sharpen.Runtime.GetBytesForString("This is the body of attach1"); database.InsertAttachmentForSequenceWithNameAndType(new ByteArrayInputStream(attach1 ), rev1.GetSequence(), testAttachmentName, "text/plain", rev1.GetGeneration()); NUnit.Framework.Assert.AreEqual(Status.Created, status.GetCode()); //We must set the no_attachments column for the rev to false, as we are using an internal //private API call above (database.insertAttachmentForSequenceWithNameAndType) which does //not set the no_attachments column on revs table try { ContentValues args = new ContentValues(); args.Put("no_attachments=", false); database.GetDatabase().Update("revs", args, "sequence=?", new string[] { rev1.GetSequence ().ToString() }); } catch (SQLException e) { Log.E(Database.Tag, "Error setting rev1 no_attachments to false", e); throw new CouchbaseLiteException(Status.InternalServerError); } Attachment attachment = database.GetAttachmentForSequence(rev1.GetSequence(), testAttachmentName ); NUnit.Framework.Assert.AreEqual("text/plain", attachment.GetContentType()); byte[] data = IOUtils.ToByteArray(attachment.GetContent()); NUnit.Framework.Assert.IsTrue(Arrays.Equals(attach1, data)); IDictionary <string, object> innerDict = new Dictionary <string, object>(); innerDict.Put("content_type", "text/plain"); innerDict.Put("digest", "sha1-gOHUOBmIMoDCrMuGyaLWzf1hQTE="); innerDict.Put("length", 27); innerDict.Put("stub", true); innerDict.Put("revpos", 1); IDictionary <string, object> attachmentDict = new Dictionary <string, object>(); attachmentDict.Put(testAttachmentName, innerDict); IDictionary <string, object> attachmentDictForSequence = database.GetAttachmentsDictForSequenceWithContent (rev1.GetSequence(), EnumSet.NoneOf <Database.TDContentOptions>()); NUnit.Framework.Assert.AreEqual(attachmentDict, attachmentDictForSequence); RevisionInternal gotRev1 = database.GetDocumentWithIDAndRev(rev1.GetDocId(), rev1 .GetRevId(), EnumSet.NoneOf <Database.TDContentOptions>()); IDictionary <string, object> gotAttachmentDict = (IDictionary <string, object>)gotRev1 .GetProperties().Get("_attachments"); NUnit.Framework.Assert.AreEqual(attachmentDict, gotAttachmentDict); // Check the attachment dict, with attachments included: Sharpen.Collections.Remove(innerDict, "stub"); innerDict.Put("data", Base64.EncodeBytes(attach1)); attachmentDictForSequence = database.GetAttachmentsDictForSequenceWithContent(rev1 .GetSequence(), EnumSet.Of(Database.TDContentOptions.TDIncludeAttachments)); NUnit.Framework.Assert.AreEqual(attachmentDict, attachmentDictForSequence); gotRev1 = database.GetDocumentWithIDAndRev(rev1.GetDocId(), rev1.GetRevId(), EnumSet .Of(Database.TDContentOptions.TDIncludeAttachments)); gotAttachmentDict = (IDictionary <string, object>)gotRev1.GetProperties().Get("_attachments" ); NUnit.Framework.Assert.AreEqual(attachmentDict, gotAttachmentDict); // Add a second revision that doesn't update the attachment: IDictionary <string, object> rev2Properties = new Dictionary <string, object>(); rev2Properties.Put("_id", rev1.GetDocId()); rev2Properties.Put("foo", 2); rev2Properties.Put("bazz", false); RevisionInternal rev2 = database.PutRevision(new RevisionInternal(rev2Properties, database), rev1.GetRevId(), false, status); NUnit.Framework.Assert.AreEqual(Status.Created, status.GetCode()); database.CopyAttachmentNamedFromSequenceToSequence(testAttachmentName, rev1.GetSequence (), rev2.GetSequence()); // Add a third revision of the same document: IDictionary <string, object> rev3Properties = new Dictionary <string, object>(); rev3Properties.Put("_id", rev2.GetDocId()); rev3Properties.Put("foo", 2); rev3Properties.Put("bazz", false); RevisionInternal rev3 = database.PutRevision(new RevisionInternal(rev3Properties, database), rev2.GetRevId(), false, status); NUnit.Framework.Assert.AreEqual(Status.Created, status.GetCode()); byte[] attach2 = Sharpen.Runtime.GetBytesForString("<html>And this is attach2</html>" ); database.InsertAttachmentForSequenceWithNameAndType(new ByteArrayInputStream(attach2 ), rev3.GetSequence(), testAttachmentName, "text/html", rev2.GetGeneration()); // Check the 2nd revision's attachment: Attachment attachment2 = database.GetAttachmentForSequence(rev2.GetSequence(), testAttachmentName ); NUnit.Framework.Assert.AreEqual("text/plain", attachment2.GetContentType()); data = IOUtils.ToByteArray(attachment2.GetContent()); NUnit.Framework.Assert.IsTrue(Arrays.Equals(attach1, data)); // Check the 3rd revision's attachment: Attachment attachment3 = database.GetAttachmentForSequence(rev3.GetSequence(), testAttachmentName ); NUnit.Framework.Assert.AreEqual("text/html", attachment3.GetContentType()); data = IOUtils.ToByteArray(attachment3.GetContent()); NUnit.Framework.Assert.IsTrue(Arrays.Equals(attach2, data)); IDictionary <string, object> attachmentDictForRev3 = (IDictionary <string, object>) database.GetAttachmentsDictForSequenceWithContent(rev3.GetSequence(), EnumSet.NoneOf <Database.TDContentOptions>()).Get(testAttachmentName); if (attachmentDictForRev3.ContainsKey("follows")) { if (((bool)attachmentDictForRev3.Get("follows")) == true) { throw new RuntimeException("Did not expected attachment dict 'follows' key to be true" ); } else { throw new RuntimeException("Did not expected attachment dict to have 'follows' key" ); } } // Examine the attachment store: NUnit.Framework.Assert.AreEqual(2, attachments.Count()); ICollection <BlobKey> expected = new HashSet <BlobKey>(); expected.AddItem(BlobStore.KeyForBlob(attach1)); expected.AddItem(BlobStore.KeyForBlob(attach2)); NUnit.Framework.Assert.AreEqual(expected, attachments.AllKeys()); database.Compact(); // This clears the body of the first revision NUnit.Framework.Assert.AreEqual(1, attachments.Count()); ICollection <BlobKey> expected2 = new HashSet <BlobKey>(); expected2.AddItem(BlobStore.KeyForBlob(attach2)); NUnit.Framework.Assert.AreEqual(expected2, attachments.AllKeys()); }