예제 #1
0
        public unsafe void TestConvertError()
        {
            var exceptions = new Exception[]
            {
                new SocketException((int)SocketError.HostNotFound),
                new SocketException((int)SocketError.HostUnreachable),
                new SocketException((int)SocketError.TimedOut),
                new SocketException((int)SocketError.ConnectionAborted),
                new SocketException((int)SocketError.ConnectionRefused),
                #if !WINDOWS_UWP
                new AuthenticationException("The remote certificate is invalid according to the validation procedure."),
                #endif
                new InvalidOperationException("Test message")
            };

            var errors = new[]
            {
                new C4Error(C4NetworkErrorCode.UnknownHost),
                new C4Error(C4NetworkErrorCode.DNSFailure),
                new C4Error(C4NetworkErrorCode.Timeout),
                new C4Error(C4ErrorDomain.POSIXDomain, PosixBase.GetCode(nameof(PosixWindows.ECONNRESET))),
                new C4Error(C4ErrorDomain.POSIXDomain, PosixBase.GetCode(nameof(PosixWindows.ECONNREFUSED))),
                #if !WINDOWS_UWP
                new C4Error(C4NetworkErrorCode.TLSCertUntrusted),
                #endif
                new C4Error(C4ErrorDomain.LiteCoreDomain, (int)C4ErrorCode.UnexpectedError)
            };

            foreach (var pair in exceptions.Zip(errors, (a, b) => new { a, b }))
            {
                C4Error tmp;
                Status.ConvertNetworkError(pair.a, &tmp);
                tmp.Should().Be(pair.b);
            }
        }
        // Run in a dedicated thread
        private async void PerformRead()
        {
            var original = _readWriteCancellationTokenSource;

            if (original == null)
            {
                Log.To.Sync.V(Tag, "_readWriteCancellationTokenSource is null, cancelling read...");
                return;
            }

            var zeroByteCount = 0;
            // This will protect us against future nullification of the original source
            var cancelSource = CancellationTokenSource.CreateLinkedTokenSource(original.Token);

            while (!cancelSource.IsCancellationRequested)
            {
                try {
                    _receivePause?.Wait(cancelSource.Token);
                } catch (ObjectDisposedException) {
                    return;
                } catch (OperationCanceledException) {
                    return;
                }

                try {
                    var stream = NetworkStream;
                    if (stream == null)
                    {
                        return;
                    }

                    // Phew, at this point we are clear to actually read from the stream
                    var received = await stream.ReadAsync(_buffer, 0, _buffer.Length, cancelSource.Token).ConfigureAwait(false);

                    if (received == 0)
                    {
                        if (zeroByteCount++ >= 10)
                        {
                            Log.To.Sync.I(Tag, "Failed to read from stream too many times, signaling closed...");
                            DidClose(new CouchbasePosixException(PosixBase.GetCode(nameof(PosixWindows.ECONNRESET))));
                            return;
                        }

                        // Should only happen on a closed stream, but just in case let's continue
                        // after a small delay (wait for cancellation to confirm)
                        Thread.Sleep(200);
                        continue;
                    }

                    zeroByteCount = 0;
                    var data = _buffer.Take(received).ToArray();
                    Receive(data);
                } catch (Exception e) {
                    DidClose(e);
                    return;
                }
            }
        }
        public void TestBusyPort()
        {
            _listener = CreateListener(false);
            //listener1 uses the same port as listener
            var config    = CreateListenerConfig(false);
            var listener1 = Listen(config, PosixBase.GetCode(nameof(PosixWindows.EADDRINUSE)), CouchbaseLiteErrorType.POSIX);

            _listener.Stop();
            listener1.Stop();
            listener1.Dispose();
        }
예제 #4
0
        public void TestErrorMessages()
        {
            var msg = Native.c4error_getMessage(new C4Error(C4ErrorDomain.LiteCoreDomain, 0));

            msg.Should().BeNull("because there was no error");

            AssertMessage(C4ErrorDomain.SQLiteDomain, (int)SQLiteStatus.Corrupt, "database disk image is malformed");
            AssertMessage(C4ErrorDomain.LiteCoreDomain, (int)C4ErrorCode.InvalidParameter, "invalid parameter");
            AssertMessage(C4ErrorDomain.POSIXDomain, PosixBase.GetCode(nameof(PosixBase.ENOENT)), "No such file or directory");
            AssertMessage(C4ErrorDomain.LiteCoreDomain, (int)C4ErrorCode.TransactionNotClosed, "transaction not closed");
            AssertMessage(C4ErrorDomain.SQLiteDomain, -1234, "unknown error (-1234)");
            AssertMessage((C4ErrorDomain)666, -1234, "unknown error domain");
        }
예제 #5
0
        public void TestTransientAndNetworkDependent()
        {
            foreach (var err in new[]
                     { "ENETRESET", "ECONNABORTED", "ECONNRESET", "ETIMEDOUT", "ECONNREFUSED" })
            {
                var code = PosixBase.GetCode(err);
                Native.c4error_mayBeTransient(new C4Error(C4ErrorDomain.POSIXDomain, code)).Should().BeTrue($"because {err} should be transient");
            }

            foreach (var err in new[]
                     { "ENETDOWN", "ENETUNREACH", "ENOTCONN", "ETIMEDOUT", "EHOSTUNREACH", "EADDRNOTAVAIL" })
            {
                var code = PosixBase.GetCode(err);
                Native.c4error_mayBeNetworkDependent(new C4Error(C4ErrorDomain.POSIXDomain, code)).Should().BeTrue($"because {err} should be network dependent");
            }
        }
예제 #6
0
        public void TestDatabaseCopy()
        {
            RunTestVariants(() =>
            {
                var doc1ID = "doc001";
                var doc2ID = "doc002";

                CreateRev(doc1ID, RevID, Body);
                CreateRev(doc2ID, RevID, Body);

                var srcPath  = Native.c4db_getPath(Db);
                var destPath = Path.Combine(Path.GetTempPath(), $"nudb.cblite2{Path.DirectorySeparatorChar}");
                C4Error error;
                var config = *(Native.c4db_getConfig(Db));

                if (!Native.c4db_deleteAtPath(destPath, &error))
                {
                    error.code.Should().Be(0);
                }

                LiteCoreBridge.Check(err =>
                {
                    var localConfig = config;
                    return(Native.c4db_copy(srcPath, destPath, &localConfig, err));
                });
                var nudb = (C4Database *)LiteCoreBridge.Check(err =>
                {
                    var localConfig = config;
                    return(Native.c4db_open(destPath, &localConfig, err));
                });

                try {
                    Native.c4db_getDocumentCount(nudb).Should().Be(2L, "because the database was seeded");
                    LiteCoreBridge.Check(err => Native.c4db_delete(nudb, err));
                }
                finally {
                    Native.c4db_free(nudb);
                }

                nudb = (C4Database *)LiteCoreBridge.Check(err =>
                {
                    var localConfig = config;
                    return(Native.c4db_open(destPath, &localConfig, err));
                });

                try {
                    CreateRev(nudb, doc1ID, RevID, Body);
                    Native.c4db_getDocumentCount(nudb).Should().Be(1L, "because a document was inserted");
                }
                finally {
                    Native.c4db_free(nudb);
                }

                var originalDest = destPath;
                destPath         = Path.Combine(Path.GetTempPath(), "bogus", $"nudb.cblite2{Path.DirectorySeparatorChar}");
                Action a         = () => LiteCoreBridge.Check(err =>
                {
                    var localConfig = config;
                    return(Native.c4db_copy(srcPath, destPath, &localConfig, err));
                });
                a.ShouldThrow <CouchbaseLiteException>().Where(e =>
                                                               e.Error == CouchbaseLiteError.NotFound && e.Domain == CouchbaseLiteErrorType.CouchbaseLite);

                nudb = (C4Database *)LiteCoreBridge.Check(err =>
                {
                    var localConfig = config;
                    return(Native.c4db_open(originalDest, &localConfig, err));
                });

                try {
                    Native.c4db_getDocumentCount(nudb).Should().Be(1L, "because the original database should remain");
                }
                finally {
                    Native.c4db_free(nudb);
                }

                var originalSrc = srcPath;
                srcPath         = $"{srcPath}bogus{Path.DirectorySeparatorChar}";
                destPath        = originalDest;
                a.ShouldThrow <CouchbaseLiteException>().Where(e =>
                                                               e.Error == CouchbaseLiteError.NotFound && e.Domain == CouchbaseLiteErrorType.CouchbaseLite);

                nudb = (C4Database *)LiteCoreBridge.Check(err =>
                {
                    var localConfig = config;
                    return(Native.c4db_open(destPath, &localConfig, err));
                });

                try {
                    Native.c4db_getDocumentCount(nudb).Should().Be(1L, "because the original database should remain");
                }
                finally {
                    Native.c4db_free(nudb);
                }

                srcPath = originalSrc;
                a.ShouldThrow <CouchbasePosixException>().Where(e =>
                                                                e.Error == PosixBase.GetCode(nameof(PosixBase.EEXIST)) && e.Domain == CouchbaseLiteErrorType.POSIX);
                nudb = (C4Database *)LiteCoreBridge.Check(err =>
                {
                    var localConfig = config;
                    return(Native.c4db_open(destPath, &localConfig, err));
                });

                try {
                    Native.c4db_getDocumentCount(nudb).Should().Be(1L, "because the database copy failed");
                    LiteCoreBridge.Check(err => Native.c4db_delete(nudb, err));
                }
                finally {
                    Native.c4db_free(nudb);
                }
            });
        }