A few more tests, still incomplete
diff --git a/OpenSSL/SSL.py b/OpenSSL/SSL.py
index 35ecf7c..e4116e2 100644
--- a/OpenSSL/SSL.py
+++ b/OpenSSL/SSL.py
@@ -143,6 +143,16 @@
 
 
 
+class WantWriteError(Error):
+    pass
+
+
+
+class WantX509LookupError(Error):
+    pass
+
+
+
 class ZeroReturnError(Error):
     pass
 
@@ -777,21 +787,27 @@
         error = _api.SSL_get_error(ssl, result)
         if error == _api.SSL_ERROR_WANT_READ:
             raise WantReadError()
+        elif error == _api.SSL_ERROR_WANT_WRITE:
+            raise WantWriteError()
         elif error == _api.SSL_ERROR_ZERO_RETURN:
             raise ZeroReturnError()
-        elif error == _api.SSL_ERROR_NONE:
-            pass
+        elif error == _api.SSL_ERROR_WANT_X509_LOOKUP:
+            # TODO Untested
+            1/0
+            raise WantX509LookupError()
         elif error == _api.SSL_ERROR_SYSCALL:
             if _api.ERR_peek_error() == 0:
                 if result < 0:
                     raise SysCallError(
                         _api.ffi.errno, errorcode[_api.ffi.errno])
                 else:
-                    # TODO
-                    raise Exception("unknown syscall error")
+                    raise SysCallError(-1, "Unexpected EOF")
             else:
-                # TODO
+                # TODO Untested
+                1/0
                 _raise_current_error(Error)
+        elif error == _api.SSL_ERROR_NONE:
+            pass
         else:
             _raise_current_error(Error)
 
@@ -930,7 +946,23 @@
         if _api.BIO_should_retry(bio):
             if _api.BIO_should_read(bio):
                 raise WantReadError()
-        1/0
+            elif _api.BIO_should_write(bio):
+                # TODO Untested
+                1/0
+                raise WantWriteError()
+            elif _api.BIO_should_io_special(bio):
+                1/0
+                # TODO Untested.  I think io_special means the socket BIO has a
+                # not-yet connected socket.
+                raise ValueError("BIO_should_io_special")
+            else:
+                1/0
+                # TODO Untested
+                raise ValueError("unknown bio failure")
+        else:
+            1/0
+            # TODO Untested
+            _raise_current_error(Error)
 
 
     def bio_read(self, bufsiz):
diff --git a/OpenSSL/crypto.py b/OpenSSL/crypto.py
index 23c533c..2fed4b8 100644
--- a/OpenSSL/crypto.py
+++ b/OpenSSL/crypto.py
@@ -286,8 +286,11 @@
         if data_length < 0:
             1/0
 
-        result = _api.buffer(result_buffer[0], data_length)[:].decode('utf-8')
-        _api.OPENSSL_free(result_buffer[0])
+        try:
+            result = _api.buffer(result_buffer[0], data_length)[:].decode('utf-8')
+        finally:
+            # XXX untested
+            _api.OPENSSL_free(result_buffer[0])
         return result
 
 
diff --git a/OpenSSL/test/test_ssl.py b/OpenSSL/test/test_ssl.py
index 8fc17a2..1b2f213 100644
--- a/OpenSSL/test/test_ssl.py
+++ b/OpenSSL/test/test_ssl.py
@@ -8,7 +8,7 @@
 from gc import collect
 from errno import ECONNREFUSED, EINPROGRESS, EWOULDBLOCK, EPIPE
 from sys import platform, version_info
-from socket import error, socket
+from socket import SHUT_RDWR, error, socket
 from os import makedirs
 from os.path import join, dirname
 from unittest import main
@@ -33,9 +33,9 @@
     SESS_CACHE_NO_INTERNAL_STORE, SESS_CACHE_NO_INTERNAL)
 
 from OpenSSL.SSL import (
-    Error, SysCallError, WantReadError, ZeroReturnError, SSLeay_version)
+    Error, SysCallError, WantReadError, WantWriteError, ZeroReturnError)
 from OpenSSL.SSL import (
-    Context, ContextType, Session, Connection, ConnectionType)
+    Context, ContextType, Session, Connection, ConnectionType, SSLeay_version)
 
 from OpenSSL.test.util import TestCase, bytes, b
 from OpenSSL.test.test_crypto import (
@@ -1239,8 +1239,6 @@
     """
     Unit tests for :py:obj:`OpenSSL.SSL.Connection`.
     """
-    # XXX want_write
-    # XXX want_read
     # XXX get_peer_certificate -> None
     # XXX sock_shutdown
     # XXX master_key -> TypeError
@@ -1729,6 +1727,36 @@
             self._loopback, clientFactory=makeClient, serverFactory=makeServer)
 
 
+    def test_wantWriteError(self):
+        """
+        :py:obj:`Connection` methods which generate output raise
+        :py:obj:`OpenSSL.SSL.WantWriteError` if writing to the connection's BIO
+        fail indicating a should-write state.
+        """
+        client_socket, server_socket = socket_pair()
+        # Fill up the client's send buffer so Connection won't be able to write
+        # anything.
+        msg = 'x' * 1024
+        for i in range(1024):
+            try:
+                client_socket.send(msg)
+            except error as e:
+                if e.errno == EWOULDBLOCK:
+                    break
+                raise
+        else:
+            self.fail(
+                "Failed to fill socket buffer, cannot test BIO want write")
+
+        ctx = Context(TLSv1_METHOD)
+        conn = Connection(ctx, client_socket)
+        # Client's speak first, so make it an SSL client
+        conn.set_connect_state()
+        self.assertRaises(WantWriteError, conn.do_handshake)
+
+    # XXX want_read
+
+
 
 class ConnectionGetCipherListTests(TestCase):
     """
@@ -2224,6 +2252,18 @@
         self.assertEquals(e.__class__, Error)
 
 
+    def test_unexpectedEndOfFile(self):
+        """
+        If the connection is lost before an orderly SSL shutdown occurs,
+        :py:obj:`OpenSSL.SSL.SysCallError` is raised with a message of
+        "Unexpected EOF".
+        """
+        server_conn, client_conn = self._loopback()
+        client_conn.sock_shutdown(SHUT_RDWR)
+        exc = self.assertRaises(SysCallError, server_conn.recv, 1024)
+        self.assertEqual(exc.args, (-1, "Unexpected EOF"))
+
+
     def _check_client_ca_list(self, func):
         """
         Verify the return value of the :py:obj:`get_client_ca_list` method for server and client connections.
@@ -2435,6 +2475,22 @@
         self._check_client_ca_list(set_replaces_add_ca)
 
 
+
+class ConnectionBIOTests(TestCase):
+    """
+    Tests for :py:obj:`Connection.bio_read` and :py:obj:`Connection.bio_write`.
+    """
+    def test_wantReadError(self):
+        """
+        :py:obj:`Connection.bio_read` raises :py:obj:`OpenSSL.SSL.WantReadError`
+        if there are no bytes available to be read from the BIO.
+        """
+        ctx = Context(TLSv1_METHOD)
+        conn = Connection(ctx, None)
+        self.assertRaises(WantReadError, conn.bio_read, 1024)
+
+
+
 class InfoConstantTests(TestCase):
     """
     Tests for assorted constants exposed for use in info callbacks.