コード例 #1
0
        public void TestDeleteBlobs()
        {
            RunTestVariants(() =>
            {
                var blobToStore = Encoding.ASCII.GetBytes("This is a blob to store in the store!");

                var key = new C4BlobKey();
                LiteCoreBridge.Check(err =>
                {
                    C4BlobKey tmp;
                    var retVal = Native.c4blob_create(_store, blobToStore, null, &tmp, err);
                    key        = tmp;
                    return(retVal);
                });

                var str = Native.c4blob_keyToString(key);
                str.Should().Be("sha1-QneWo5IYIQ0ZrbCG0hXPGC6jy7E=");

                LiteCoreBridge.Check(err => Native.c4blob_delete(_store, key, err));

                var blobSize = Native.c4blob_getSize(_store, key);
                blobSize.Should().Be(-1L, "because the blob was deleted");

                var gotBlob = Native.c4blob_getContents(_store, key, null);
                gotBlob.Should().BeNull("because the blob was deleted");

                C4Error error;
                var p = Native.c4blob_getFilePath(_store, key, &error);
                p.Should().BeNull("because the blob was deleted");
                error.domain.Should().Be(C4ErrorDomain.LiteCoreDomain);
                error.code.Should().Be((int)C4ErrorCode.NotFound);
            });
        }
コード例 #2
0
        public void TestCreateBlobKeyMismatch()
        {
            RunTestVariants(() =>
            {
                var blobToStore            = C4Slice.Constant("This is a blob to store in the store!");
                C4BlobKey key, expectedKey = new C4BlobKey();
                var i = 0;
                foreach (var b in Enumerable.Repeat <byte>(0x55, sizeof(C4BlobKey)))
                {
                    expectedKey.bytes[i++] = b;
                }

                C4Error error;
                NativePrivate.c4log_warnOnErrors(false);
                try {
                    NativeRaw.c4blob_create(_store, blobToStore, &expectedKey, &key, &error).Should().BeFalse();
                    error.domain.Should().Be(C4ErrorDomain.LiteCoreDomain);
                    error.code.Should().Be((int)C4ErrorCode.CorruptData);
                } finally {
                    NativePrivate.c4log_warnOnErrors(true);
                }

                Native.c4blob_keyFromString("sha1-QneWo5IYIQ0ZrbCG0hXPGC6jy7E=", &expectedKey);
                NativeRaw.c4blob_create(_store, blobToStore, &expectedKey, &key, &error).Should().BeTrue();
            });
        }
コード例 #3
0
        public void TestCreateBlobs()
        {
            RunTestVariants(() => {
                var blobToStore = Encoding.UTF8.GetBytes("This is a blob to store in the store!");

                // Add the blob to the store:
                var key      = new C4BlobKey();
                var localKey = &key;
                LiteCoreBridge.Check(err => {
                    return(Native.c4blob_create(_store, blobToStore, null, localKey, err));
                });

                var str = Native.c4blob_keyToString(key);
                str.Should().Be("sha1-QneWo5IYIQ0ZrbCG0hXPGC6jy7E=", "because the blob key should hash correctly");

                // Read it back and compare
                var blobSize = Native.c4blob_getSize(_store, key);
                blobSize.Should().BeGreaterOrEqualTo(blobToStore.Length, "because the size should be a conservative estimate, never lower");
                if (_encrypted)
                {
                    blobSize.Should().BeLessOrEqualTo(blobToStore.Length + 16, "because the estimate should never be more than 16 bytes off");
                }
                else
                {
                    blobSize.Should().Be(blobToStore.Length, "because unecrypted blobs should have the exact size");
                }

                C4Error error;
                var gotBlob = Native.c4blob_getContents(_store, key, &error);
                gotBlob.Should().NotBeNull("because the attachment should be readable");
                blobToStore.Should().Equal(gotBlob, "because the attachment shouldn't change");

                var p = Native.c4blob_getFilePath(_store, key, &error);
                if (_encrypted)
                {
                    p.Should().BeNull("because an encrypted store will not return a file path");
                    error.code.Should().Be((int)C4ErrorCode.WrongFormat, "because otherwise an unexpected error occurred");
                }
                else
                {
                    p.Should().NotBeNull("because otherwise the DB failed to return its blob store");
                    var filename = "QneWo5IYIQ0ZrbCG0hXPGC6jy7E=.blob";
                    Path.GetFileName(p).Should().Be(filename, "because otherwise the store returned an invalid filename");
                }

                // Try storing it again
                var key2 = new C4BlobKey();
                localKey = &key2;
                LiteCoreBridge.Check(err => {
                    return(Native.c4blob_create(_store, blobToStore, null, localKey, err));
                });

                for (int i = 0; i < C4BlobKey.Size; i++)
                {
                    key.bytes[i].Should().Be(key2.bytes[i]);
                }
            });
        }
コード例 #4
0
        public void TestDatabaseRekey()
        {
            RunTestVariants(() =>
            {
                CreateNumberedDocs(99);

                // Add blob to the store:
                var blobToStore = C4Slice.Constant("This is a blob to store in the store!");
                var blobKey     = new C4BlobKey();
                var blobStore   = (C4BlobStore *)LiteCoreBridge.Check(err => Native.c4db_getBlobStore(Db, err));
                LiteCoreBridge.Check(err =>
                {
                    C4BlobKey local;
                    var retVal = NativeRaw.c4blob_create(blobStore, blobToStore, null, &local, err);
                    blobKey    = local;
                    return(retVal);
                });

                C4Error error;
                var blobResult = NativeRaw.c4blob_getContents(blobStore, blobKey, &error);
                ((C4Slice)blobResult).Should().Equal(blobToStore);
                Native.c4slice_free(blobResult);

                // If we're on the unexcrypted pass, encrypt the db.  Otherwise, decrypt it:
                var newKey = new C4EncryptionKey();
                if (Native.c4db_getConfig(Db)->encryptionKey.algorithm == C4EncryptionAlgorithm.None)
                {
                    newKey.algorithm = C4EncryptionAlgorithm.AES256;
                    var keyBytes     = Encoding.ASCII.GetBytes("a different key than default....");
                    Marshal.Copy(keyBytes, 0, (IntPtr)newKey.bytes, 32);
                }

                var tmp = newKey;
                LiteCoreBridge.Check(err =>
                {
                    var local = tmp;
                    return(Native.c4db_rekey(Db, &local, err));
                });

                // Verify the db works:
                Native.c4db_getDocumentCount(Db).Should().Be(99);
                ((IntPtr)blobStore).Should().NotBe(IntPtr.Zero);
                blobResult = NativeRaw.c4blob_getContents(blobStore, blobKey, &error);
                ((C4Slice)blobResult).Should().Equal(blobToStore);
                Native.c4slice_free(blobResult);

                // Check thqat db can be reopened with the new key:
                Native.c4db_getConfig(Db)->encryptionKey.algorithm.Should().Be(newKey.algorithm);
                for (int i = 0; i < 32; i++)
                {
                    Native.c4db_getConfig(Db)->encryptionKey.bytes[i].Should().Be(newKey.bytes[i]);
                }

                ReopenDB();
            });
        }
コード例 #5
0
        internal C4BlobKey[] AddDocWithAttachments(C4Slice docID, List <string> atts, string contentType)
        {
            var keys = new List <C4BlobKey>();
            var json = new StringBuilder();

            json.Append("{attached: [");
            foreach (var att in atts)
            {
                var key = new C4BlobKey();
                LiteCoreBridge.Check(err =>
                {
                    var localKey = key;
                    var retVal   = Native.c4blob_create(Native.c4db_getBlobStore(Db, null), Encoding.UTF8.GetBytes(att),
                                                        null, &localKey, err);
                    key = localKey;
                    return(retVal);
                });

                keys.Add(key);
                var keyStr = Native.c4blob_keyToString(key);
                json.Append(
                    $"{{'{Constants.ObjectTypeProperty}': '{Constants.ObjectTypeBlob}', 'digest': '{keyStr}', length: {att.Length}, 'content_type': '{contentType}'}},");
            }

            json.Append("]}");
            var jsonStr = Native.FLJSON5_ToJSON(json.ToString(), null);

            using (var jsonStr_ = new C4String(jsonStr)) {
                C4Error error;
                var     body = NativeRaw.c4db_encodeJSON(Db, jsonStr_.AsC4Slice(), &error);
                ((long)body.buf).Should().NotBe(0, "because otherwise the encode failed");

                var rq = new C4DocPutRequest();
                rq.docID    = docID;
                rq.revFlags = C4RevisionFlags.HasAttachments;
                rq.body     = (C4Slice)body;
                rq.save     = true;
                var doc = Native.c4doc_put(Db, &rq, null, &error);
                Native.c4slice_free(body);
                ((long)doc).Should().NotBe(0, "because otherwise the put failed");
                Native.c4doc_free(doc);
                return(keys.ToArray());
            }
        }
コード例 #6
0
        public void TestReadBlobWithStream()
        {
            RunTestVariants(() => {
                var blob = Encoding.UTF8.GetBytes("This is a blob to store in the store!");

                // Add blob to the store:
                var key = new C4BlobKey();
                LiteCoreBridge.Check(err => {
                    var localKey = key;
                    var retVal   = Native.c4blob_create(_store, blob, null, &localKey, err);
                    key          = localKey;
                    return(retVal);
                });
                C4Error error;
                ((long)Native.c4blob_openReadStream(_store, _bogusKey, &error)).Should().Be(0,
                                                                                            "because an invalid key should not have a stream");
                var stream = (C4ReadStream *)LiteCoreBridge.Check(err => Native.c4blob_openReadStream(_store,
                                                                                                      key, err));
                Native.c4stream_getLength(stream, &error).Should().Be(blob.Length,
                                                                      "because the stream should know its own length");

                // Read it back, 6 bytes at a time:
                var buffer      = new byte[6];
                var readBack    = new List <byte>();
                ulong bytesRead = 0;
                do
                {
                    bytesRead = Native.c4stream_read(stream, buffer, &error);
                    bytesRead.Should().BeGreaterThan(0, "because there should be new bytes");
                    readBack.AddRange(buffer.Take((int)bytesRead));
                } while(bytesRead == (ulong)buffer.Length);
                error.code.Should().Be(0, "because otherwise an error occurred");
                readBack.Should().Equal(blob, "because the data should persist correctly");

                // Try seeking:
                LiteCoreBridge.Check(err => Native.c4stream_seek(stream, 10, err));
                Native.c4stream_read(stream, buffer, 4, &error).Should().Be(4, "because reading should succeed after seeking");

                Native.c4stream_close(stream);
                Native.c4stream_close(null); // This should be a no-op, not a crash
            });
        }
コード例 #7
0
        public void TestCreateBlobs()
        {
            RunTestVariants(() => {
                var blobToStore = Encoding.UTF8.GetBytes("This is a blob to store in the store!");

                // Add the blob to the store:
                var key      = new C4BlobKey();
                var localKey = &key;
                LiteCoreBridge.Check(err => {
                    return(Native.c4blob_create(_store, blobToStore, localKey, err));
                });

                var str = Native.c4blob_keyToString(key);
                str.Should().Be("sha1-QneWo5IYIQ0ZrbCG0hXPGC6jy7E=", "because the blob key should hash correctly");

                // Read it back and compare
                var blobSize = Native.c4blob_getSize(_store, key);
                blobSize.Should().BeGreaterOrEqualTo(blobToStore.Length, "because the size should be a conservative estimate, never lower");
                if (_encrypted)
                {
                    blobSize.Should().BeLessOrEqualTo(blobToStore.Length + 16, "because the estimate should never be more than 16 bytes off");
                }
                else
                {
                    blobSize.Should().Be(blobToStore.Length, "because unecrypted blobs should have the exact size");
                }

                C4Error error;
                var gotBlob = Native.c4blob_getContents(_store, key, &error);
                gotBlob.Should().NotBeNull("because the attachment should be readable");
                blobToStore.Should().Equal(gotBlob, "because the attachment shouldn't change");

                // Try storing it again
                var key2 = new C4BlobKey();
                localKey = &key2;
                LiteCoreBridge.Check(err => {
                    return(Native.c4blob_create(_store, blobToStore, localKey, err));
                });
                key.Equals(key2).Should().BeTrue("because the two keys are for the same attachment");
            });
        }
コード例 #8
0
        public void TestParseBlobKeys()
        {
            var key1 = new C4BlobKey();

            for (int i = 0; i < C4BlobKey.Size; i++)
            {
                key1.bytes[i] = 0x55;
            }

            var str = Native.c4blob_keyToString(key1);

            str.Should().Be("sha1-VVVVVVVVVVVVVVVVVVVVVVVVVVU=", "because otherwise the parse failed");

            var key2 = new C4BlobKey();

            Native.c4blob_keyFromString(str, &key2).Should().BeTrue("because the key should survive a round trip");
            for (int i = 0; i < C4BlobKey.Size; i++)
            {
                key1.bytes[i].Should().Be(key2.bytes[i], "because the two keys should have equal bytes");
            }
        }
コード例 #9
0
 public static C4ReadStream *c4blob_openReadStream(C4BlobStore *store, C4BlobKey key, C4Error *outError) => Impl.c4blob_openReadStream(store, key, outError);
コード例 #10
0
 public static bool c4blob_delete(C4BlobStore *store, C4BlobKey key, C4Error *outError) => Impl.c4blob_delete(store, key, outError);
コード例 #11
0
 public static string c4blob_getFilePath(C4BlobStore *store, C4BlobKey key, C4Error *outError) => Impl.c4blob_getFilePath(store, key, outError);
コード例 #12
0
 public static byte[] c4blob_getContents(C4BlobStore *store, C4BlobKey key, C4Error *outError) => Impl.c4blob_getContents(store, key, outError);
コード例 #13
0
 public static long c4blob_getSize(C4BlobStore *store, C4BlobKey key) => Impl.c4blob_getSize(store, key);
コード例 #14
0
 public static string c4blob_keyToString(C4BlobKey key) => Impl.c4blob_keyToString(key);
コード例 #15
0
 public static FLSliceResult c4blob_getContents(C4BlobStore *store, C4BlobKey key, C4Error *outError) => Impl.c4blob_getContents(store, key, outError);
コード例 #16
0
 public static FLSliceResult c4blob_keyToString(C4BlobKey key) => Impl.c4blob_keyToString(key);