broke the monster PKCS12 test into little ones, and other PKCS12 test additions.
diff --git a/test/test_crypto.py b/test/test_crypto.py
index 047d910..5149947 100644
--- a/test/test_crypto.py
+++ b/test/test_crypto.py
@@ -20,6 +20,7 @@
 from OpenSSL.crypto import PKCS12Type, load_pkcs12, PKCS12
 from OpenSSL.crypto import NetscapeSPKI, NetscapeSPKIType
 from OpenSSL.test.util import TestCase
+from OpenSSL.test.test_ssl import client_cert_pem, client_key_pem, server_cert_pem, server_key_pem, root_cert_pem
 
 cleartextCertificatePEM = """-----BEGIN CERTIFICATE-----
 MIIC7TCCAlagAwIBAgIIPQzE4MbeufQwDQYJKoZIhvcNAQEFBQAwWDELMAkGA1UE
@@ -92,57 +93,6 @@
 """
 encryptedPrivateKeyPEMPassphrase = "foobar"
 
-# Some PKCS12 data, base64 encoded.  The data itself was constructed using the
-# openssl command line:
-#
-#    openssl pkcs12 -export -in s.pem -out o.p12 -inkey s.pem -certfile s.pem
-#
-# With s.pem containing a private key and certificate.  The contents of the
-# generated file, o.p12, were then base64 encoded to produce this value.
-pkcs12Data = """\
-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
-""".decode('base64')
-
 # Some PKCS#7 stuff.  Generated with the openssl command line:
 #
 #    openssl crl2pkcs7 -inform pem -outform pem -certfile s.pem -nocrl
@@ -737,11 +687,12 @@
     """
     pemData = cleartextCertificatePEM + cleartextPrivateKeyPEM
 
-    def test_construction(self):
+    def test_empty_construction(self):
         """
         Confirm L{OpenSSL.crypto.PKCS12} returs a PKCS12.  Confirm
         that the new PKCS12 is empty.
         """
+        self.assertTrue(type(PKCS12).__name__, 'PKCS12')
         p12 = PKCS12() 
         self.assertTrue(isinstance(p12, PKCS12))
         self.assertEqual(None, p12.get_certificate())
@@ -752,14 +703,19 @@
     def test_type_errors(self):
         """
         Try the set functions L{OpenSSL.crypto.PKCS12} with bad
-        types to see they raise TypeError.
+        types to see them raise TypeError.
         """
         p12 = PKCS12() 
         self.assertRaises(TypeError, p12.set_certificate, 3)
+        self.assertRaises(TypeError, p12.set_certificate, PKey())
+        self.assertRaises(TypeError, p12.set_certificate, X509)
         self.assertRaises(TypeError, p12.set_privatekey, 3)
+        self.assertRaises(TypeError, p12.set_privatekey, 'legbone')
+        self.assertRaises(TypeError, p12.set_privatekey, X509())
         self.assertRaises(TypeError, p12.set_ca_certificates, 3)
         self.assertRaises(TypeError, p12.set_ca_certificates, X509())
         self.assertRaises(TypeError, p12.set_ca_certificates, (3, 4))
+        self.assertRaises(TypeError, p12.set_ca_certificates, ( PKey(), ))
 
 
     def test_key_only(self):
@@ -771,8 +727,7 @@
         passwd = 'blah'
         p12 = PKCS12()
         pkey = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM) 
-        ret = p12.set_privatekey( pkey )
-        self.assertEqual(ret, None)
+        p12.set_privatekey( pkey )
         self.assertEqual(None, p12.get_certificate())
         self.assertEqual(pkey, p12.get_privatekey())
         dumped_p12 = p12.export(passphrase=passwd, iter=2, maciter=3)
@@ -792,8 +747,7 @@
         passwd = 'blah'
         p12 = PKCS12()
         cert = load_certificate(FILETYPE_PEM, cleartextCertificatePEM) 
-        ret = p12.set_certificate( cert )
-        self.assertEqual(ret, None)
+        p12.set_certificate( cert )
         self.assertEqual(cert, p12.get_certificate())
         self.assertEqual(None, p12.get_privatekey())
         dumped_p12 = p12.export(passphrase=passwd, iter=2, maciter=3)
@@ -803,86 +757,162 @@
         self.assertEqual(cleartextCertificatePEM, dump_certificate(FILETYPE_PEM, p12.get_ca_certificates()[0]))
 
 
-    def test_export_and_load(self):
+    def gen_pkcs12( self, cert_pem, key_pem, ca_pem ):
         """
-        This monster will be divided up.
+        Generate a PKCS12 object with components from PEM.
+        Verify that the set functions return None.
         """
-        from OpenSSL.test.test_ssl import client_cert_pem, client_key_pem, server_cert_pem, server_key_pem, root_cert_pem
-        # use openssl program to create a p12 then load it
+        p12 = PKCS12()
+        if cert_pem:
+            ret = p12.set_certificate(load_certificate(FILETYPE_PEM, cert_pem))
+            self.assertEqual(ret, None)
+        if key_pem:
+            ret = p12.set_privatekey( load_privatekey(FILETYPE_PEM, key_pem) )
+            self.assertEqual(ret, None)
+        if ca_pem:
+            ret = p12.set_ca_certificates( ( load_certificate(FILETYPE_PEM, ca_pem), ) )
+            self.assertEqual(ret, None)
+        return p12
+
+
+    def check_recovery(self, p12_str, key=None, cert=None, ca=None, 
+                       passwd='', extra=()):
+        """
+        Use openssl program to confirm three components are recoverable 
+        from a PKCS12 string.
+        """
+        if key:
+            recovered_key = _runopenssl(p12_str, "pkcs12", '-nocerts', '-nodes',
+                                '-passin', 'pass:'+passwd, *extra ) 
+            self.assertEqual(recovered_key[-len(key):], key)
+        if cert:
+            recovered_cert = _runopenssl(p12_str, "pkcs12", '-clcerts', '-nodes', 
+                               '-passin', 'pass:'+passwd, '-nokeys', *extra)
+            self.assertEqual(recovered_cert[-len(cert):], cert)
+        if ca:
+            recovered_cert = _runopenssl(p12_str, "pkcs12", '-cacerts', '-nodes', 
+                                '-passin', 'pass:'+passwd, '-nokeys', *extra)
+            self.assertEqual(recovered_cert[-len(ca):], ca)
+
+
+    def test_load_pkcs12(self):
+        """
+        Generate a PKCS12 string using openssl, then load it with
+        L{load_pkcs12} and verify the returned object.
+        """
         passwd = 'whatever'
         pem = client_key_pem + client_cert_pem
-        p12_str = _runopenssl(pem, "pkcs12", '-export', '-clcerts', '-passout', 'pass:'+passwd)
+        p12_str = _runopenssl(pem, "pkcs12", '-export', '-clcerts', 
+                                   '-passout', 'pass:'+passwd)
         p12 = load_pkcs12(p12_str, passwd)
-        # verify p12 using pkcs12 get_* functions
+        # verify 
+        self.assertTrue(isinstance(p12, PKCS12))
+        self.assertTrue(isinstance(p12, PKCS12Type))
         cert_pem = dump_certificate(FILETYPE_PEM, p12.get_certificate())
         self.assertEqual(cert_pem, client_cert_pem)
         key_pem = dump_privatekey(FILETYPE_PEM, p12.get_privatekey())
         self.assertEqual(key_pem, client_key_pem)
         self.assertEqual(None, p12.get_ca_certificates())
-        # dump cert and verify it using the openssl program
-        dumped_p12 = p12.export(passphrase=passwd, iter=2, maciter=0, friendly_name='blueberry')
-        recovered_key = _runopenssl(dumped_p12, "pkcs12", '-nocerts', '-nodes', '-passin', 'pass:'+passwd)
-        self.assertEqual(recovered_key[-len(client_key_pem):], client_key_pem)
-        recovered_cert = _runopenssl(dumped_p12, "pkcs12", '-clcerts', '-nodes', '-passin', 'pass:'+passwd, '-nokeys')
-        self.assertEqual(recovered_cert[-len(client_cert_pem):], client_cert_pem)
-        # change the cert and key
-        p12.set_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
-        p12.set_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
+
+ 
+    def test_replace(self):
+        """
+        Test replacing components of a L{PKCS12} object.  Test multiple
+        CA certificates.
+        """
+        p12 = self.gen_pkcs12( client_cert_pem, client_key_pem, root_cert_pem )
+        p12.set_certificate( load_certificate(FILETYPE_PEM, server_cert_pem) )
+        p12.set_privatekey( load_privatekey(FILETYPE_PEM, server_key_pem) )
         root_cert = load_certificate(FILETYPE_PEM, root_cert_pem) 
-        p12.set_ca_certificates( [ root_cert ] )
-        ret = p12.set_ca_certificates( ( root_cert, ) )
-        self.assertEqual(ret, None)
+        client_cert = load_certificate(FILETYPE_PEM, client_cert_pem)
+        p12.set_ca_certificates( [ root_cert, ] )  # not a tuple
         self.assertEqual(1, len(p12.get_ca_certificates()))
         self.assertEqual(root_cert, p12.get_ca_certificates()[0])
-        # recover changed cert and key using the openssl program
-        dumped_p12 = p12.export(passphrase=passwd, iter=2, maciter=0, friendly_name='Serverlicious')
-        recovered_key = _runopenssl(dumped_p12, "pkcs12", '-nocerts', '-nodes', '-passin', 'pass:'+passwd)
-        self.assertEqual(recovered_key[-len(server_key_pem):], server_key_pem)
-        recovered_cert = _runopenssl(dumped_p12, "pkcs12", '-clcerts', '-nodes', '-passin', 'pass:'+passwd, '-nokeys')
-        self.assertEqual(recovered_cert[-len(server_cert_pem):], server_cert_pem)
-        recovered_cert = _runopenssl(dumped_p12, "pkcs12", '-cacerts', '-nodes', '-passin', 'pass:'+passwd, '-nokeys')
-        self.assertEqual(recovered_cert[-len(root_cert_pem):], root_cert_pem)
-        #  Test other forms of no password
+        p12.set_ca_certificates( [ client_cert, root_cert ] )
+        self.assertEqual(2, len(p12.get_ca_certificates()))
+        self.assertEqual(client_cert, p12.get_ca_certificates()[0])
+        self.assertEqual(root_cert, p12.get_ca_certificates()[1])
+
+
+    def test_friendly_name(self):
+        """
+        Test that we can export a L{PKCS12} with a friendly name.
+        """
+        p12 = self.gen_pkcs12( server_cert_pem, server_key_pem, root_cert_pem )
+        passwd = 'Dogmeat[]{}!@#$%^&*()~`?/.,<>-_+=";:'
+        for friendly_name in ('Serverlicious', None, '', '###'):
+            dumped_p12 = p12.export(passphrase=passwd, iter=2, maciter=3, 
+                                friendly_name=friendly_name)
+            self.check_recovery(dumped_p12, key=server_key_pem, 
+                    cert=server_cert_pem, ca=root_cert_pem, passwd=passwd)
+
+
+    def test_various_empty_passphrases(self):
+        """
+        Test that missing, None, and '' passphrases are identical
+        for PKCS12 export.
+        """
+        p12 = self.gen_pkcs12( client_cert_pem, client_key_pem, root_cert_pem )
         passwd = ''
-        dumped_p12_empty = p12.export(passphrase=passwd, iter=2, maciter=0, friendly_name='Sewer')
-        dumped_p12_none  = p12.export(passphrase=None,   iter=2, maciter=0, friendly_name='Sewer')
-        dumped_p12_nopw  = p12.export(                   iter=2, maciter=0, friendly_name='Sewer')
-        recovered_empty = _runopenssl(dumped_p12_empty, "pkcs12", '-nodes', '-passin', 'pass:'+passwd )
-        recovered_none  = _runopenssl(dumped_p12_none, "pkcs12", '-nodes', '-passin', 'pass:'+passwd )
-        recovered_nopw  = _runopenssl(dumped_p12_nopw, "pkcs12", '-nodes', '-passin', 'pass:'+passwd )
-        self.assertEqual(recovered_none, recovered_nopw)
-        self.assertEqual(recovered_none, recovered_empty)
-        #  Test removing CA certs
+        dumped_p12_empty = p12.export(passphrase=passwd, iter=2, maciter=0)
+        dumped_p12_none  = p12.export(passphrase=None,   iter=3, maciter=2)
+        dumped_p12_nopw  = p12.export(                   iter=9, maciter=4)
+        for dumped_p12 in ( dumped_p12_empty, dumped_p12_none, dumped_p12_nopw ):
+            self.check_recovery( dumped_p12, key=client_key_pem, 
+                    cert=client_cert_pem, ca=root_cert_pem, passwd=passwd)
+
+
+    def test_removing_ca_cert(self):
+        """
+        Test that we can remove a CA cert from a PKCS12 object.
+        """
+        p12 = self.gen_pkcs12( server_cert_pem, server_key_pem, root_cert_pem )
         p12.set_ca_certificates( None )
         self.assertEqual(None, p12.get_ca_certificates())
-        #  Test without MAC
+
+
+    def test_export_without_mac(self):
+        """
+        Export a PKCS12 without a MAC (message integrity checksum).
+        Verify it with the openssl program.
+        """
+        passwd = 'Lake Michigan'
+        p12 = self.gen_pkcs12( server_cert_pem, server_key_pem, root_cert_pem )
         dumped_p12 = p12.export(maciter=-1, passphrase=passwd, iter=2)
-        recovered_key = _runopenssl(dumped_p12, "pkcs12", '-nocerts', '-nodes', '-passin', 'pass:'+passwd, '-nomacver' )
-        self.assertEqual(recovered_key[-len(server_key_pem):], server_key_pem)
+        self.check_recovery(dumped_p12, key=server_key_pem, 
+                cert=server_cert_pem, passwd=passwd, extra=( '-nomacver', ))
         #  We can't load PKCS12 without MAC, because we use PCKS_parse()
         #p12 = load_pkcs12(dumped_p12, passwd)
-        # Test export without any args
-        dumped_p12 = p12.export()
-        recovered_key = _runopenssl(dumped_p12, "pkcs12", '-nodes', '-passin', 'pass:' )
-        self.assertEqual(recovered_key[-len(server_key_pem):], server_key_pem)
 
 
-    def test_load_pkcs12(self):
+    def test_export_without_args(self):
         """
-        L{load_pkcs12} accepts a PKCS#12 string and returns an instance of
-        L{PKCS12Type}.
+        Run L{OpenSSL.crypto.PKCS12.export} without any
+        args to show they are all truely optional.  Confirm
+        with openssl program.
         """
-        pkcs12 = load_pkcs12(pkcs12Data)
-        self.assertTrue(isinstance(pkcs12, PKCS12Type))
+        p12 = self.gen_pkcs12( server_cert_pem, server_key_pem, root_cert_pem )
+        dumped_p12 = p12.export()  # no args
+        self.check_recovery( dumped_p12, key=server_key_pem, 
+                cert=server_cert_pem, passwd='')
+
+
+    def test_key_cert_mismatch(self):
+        """
+        Verify L{OpenSSL.crypto.PKCS12.export} raises an exception when a
+        key and certificate mismatch.
+        """
+        p12 = self.gen_pkcs12( server_cert_pem, client_key_pem, root_cert_pem )
+        self.assertRaises( Error, p12.export )
 
 
 
 def _runopenssl(pem, *args):
     """
     Run the command line openssl tool with the given arguments and write
-    the given PEM to its stdin.
+    the given PEM to its stdin.  Not safe for single quotes.
     """
-    write, read = popen2(" ".join(("openssl",) + args), "b")
+    write, read = popen2("'" + "' '".join(("openssl",) + args) + "'", "b")
     write.write(pem)
     write.close()
     return read.read()