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(); }
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"); }
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"); } }
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); } }); }