Esempio n. 1
0
class ModelTestSuite(unittest.TestCase):
    def setUp(self):
        self.db = MarketDatabase(MemoryBackend())
        self.api = MarketAPI(self.db)

        self.db.backend.set_option('user_key_pub', "3081a7301006072a8648ce3d020106052b810400270381920004040a3d5712482be45375958745cdd3134ff079303bcf0ecf02ff6dff5b49cfde221a4068f1a243e31ba36052ed4836c77df8c1729cb9875ed703b23ccc9488f0b81ddba6e51b1caa01bc4e4c0152554c38b805ae6d9fb9d0a20172266b814a4f20e5ced5eb8f657c521b76dc6c10eb695444d69db8426a39232bd3e166eb22bcb7704642ca26a276774dc13d249b9e29")
        self.db.backend.set_option('user_key_priv', "3081ee0201010448017a656efdf1a6203fee24074e8e9aba1c329563321bbb17ddc069fccee0b9b5e5b505f4ac2131760b82cfb56301cac7a00341c812b7ae6b4867910c5ac8d4c23152ccaf64ba7956a00706052b81040027a181950381920004040a3d5712482be45375958745cdd3134ff079303bcf0ecf02ff6dff5b49cfde221a4068f1a243e31ba36052ed4836c77df8c1729cb9875ed703b23ccc9488f0b81ddba6e51b1caa01bc4e4c0152554c38b805ae6d9fb9d0a20172266b814a4f20e5ced5eb8f657c521b76dc6c10eb695444d69db8426a39232bd3e166eb22bcb7704642ca26a276774dc13d249b9e29")

    def test_signed_model_no_save(self):
        """
        Test if signing an unsaved model raises an error.
        """
        model = DatabaseModel()

        with self.assertRaises(RuntimeError):
            model.sign(self.api)

    def test_signed_model(self):
        """
        Test is models can be signed, and if the signature is read as valid
        """
        model = DatabaseModel()
        model.post_or_put(self.db)

        pre_hash = model.generate_sha1_hash()
        # Sign the model
        model.sign(self.api)
        post_hash = model.generate_sha1_hash()

        self.assertEqual(pre_hash, post_hash)
        self.assertEqual(model.signer, self.db.backend.get_option('user_key_pub'))
        self.assertTrue(DatabaseModel.signature_valid(model))

    def test_signed_model_detect_tamper(self):
        """
        Test is models can be signed, and if the signature is read as valid
        """
        model = DatabaseModel()
        model.post_or_put(self.db)

        pre_hash = model.generate_sha1_hash()
        # Sign the model
        model.sign(self.api)

        #Tamper with the model
        model._id = 'different'

        post_hash = model.generate_sha1_hash()

        self.assertNotEqual(pre_hash, post_hash)
        self.assertEqual(model.signer, self.db.backend.get_option('user_key_pub'))
        self.assertFalse(DatabaseModel.signature_valid(model))


    def test_model_equal(self):
        """
        Test if identical models have the same hash and are eveluated as equal
        """
        model1 = DatabaseModel()
        model2 = DatabaseModel()

        #self.assertEqual(hash(model1), hash(model2))
        self.assertEqual(model1, model2)

    def test_model_unequal(self):
        """
        Test if different models have different hashes and are evaluated as unequal
        """
        model1 = DatabaseModel()
        model2 = DatabaseModel()

        # Change the models by saving one and giving it an id
        model2.post_or_put(self.db)

        self.assertNotEqual(hash(model1), hash(model2))
        self.assertNotEqual(model1, model2)

    def test_post_or_put_time(self):
        model = DatabaseModel()

        # Save the model, sign it, then save the signed version.
        model.post_or_put(self.db)
        model.sign(self.api)
        model.post_or_put(self.db)

        original_sign_time = model.time_signed

        # get a copy
        model_copy = self.db.get('database_model', model.id)

        self.assertEqual(original_sign_time, model_copy.time_signed)

        model_copy.sign(self.api)
        new_sign_time = model.time_signed
        model_copy.post_or_put(self.db)

        model_new_copy = self.db.get('database_model', model.id)
        self.assertEqual(new_sign_time, model_new_copy.time_signed)

        # Now we check that older models arent saved.
        model_new_copy._time_signed = 0
        model_new_copy.post_or_put(self.db, check_time=True)

        model_last_copy = self.db.get('database_model', model.id)
        self.assertEqual(new_sign_time, model_last_copy.time_signed)

    def test_user_key_immutable(self):
        """
        Test is an error is raised when attempting to change the user key.
        """
        public_key = 'pk'
        time_added = 100

        user = User(public_key, time_added)
        user.post_or_put(self.api.db)

        self.assertEqual(user.time_added, time_added)
        with self.assertRaises(IndexError) as cm:
            user.generate_id(force=True)

        exception = cm.exception
        self.assertEqual(exception.message, "User key is immutable")


    def test_document_model(self):
        file_name = 'test.py'
        mime = 'text/x-python'
        file_path = os.path.join(os.path.dirname(sys.modules['market'].__file__), '__init__.py')
        document = Document.encode_document(file_name, file_path)

        self.assertTrue(isinstance(document, Document))
        self.assertEqual(document.name, file_name)
        self.assertEqual(document.mime, mime)

        this_folder = os.getcwd()
        document.decode_document(os.path.join(this_folder, file_name))
        new_file_path = os.path.join(this_folder, file_name)

        self.assertEqual(open(file_path).read(), open(new_file_path).read())

        # Cleanup
        os.remove(new_file_path)
class MarketDatabaseTestSuite(unittest.TestCase):
    def setUp(self):
        self.database = MarketDatabase(MemoryBackend())

        # Some database models
        self.model1 = DatabaseModel()
        self.model2 = DatabaseModel()

    def test_init(self):
        database = MarketDatabase(MemoryBackend())

        # Raise an error if no backend is given
        with self.assertRaises(AssertionError):
            database2 = MarketDatabase(None)

    def test_post(self):
        # Check if it has no id prior to saving
        self.assertIsNone(self.model1.id)

        id = self.database.post(self.model1.type, self.model1)

        # Check if id saved to model
        self.assertEqual(
            self.model1.id,
            self.database.get(self.model1.type, self.model1.id).id)

    def test_get(self):
        self.database.post(self.model1.type, self.model1)

        # Get the same object
        self.assertEqual(self.model1,
                         self.database.get(self.model1.type, self.model1.id))

        # Get a noneexisting model
        self.assertIsNone(self.database.get(self.model1.type, 'invalid_id'))

    def test_put(self):
        # Put an unsaved model
        with self.assertRaises(AssertionError):
            self.assertFalse(
                self.database.put(self.model1.type, self.model1.id,
                                  self.model1))

        # Fake an id
        self.model1._id = "fake"

        # Replace a nonexisting element
        self.assertFalse(
            self.database.put(self.model1.type, self.model1.id, self.model1))

        # Replace an existing element correctly
        test_string = "boo"
        with self.assertRaises(AttributeError):
            self.assertEqual(self.model1.test, test_string)

        self.model1.test = test_string
        self.database.post(self.model1.type, self.model1)

        # Check if the test string was saved in the db
        self.assertEqual(
            self.database.get(self.model1.type, self.model1.id).test,
            test_string)

        # Change the string
        test_string2 = "baa"
        self.model1.test = test_string2
        self.assertTrue(
            self.database.put(self.model1.type, self.model1.id, self.model1))
        self.assertEqual(
            self.database.get(self.model1.type, self.model1.id).test,
            test_string2)

        # Finally check if we can't replace it with another id
        self.model2._id = "not_id_of_model1"
        with self.assertRaises(AssertionError):
            self.assertFalse(
                self.database.put(self.model1.type, self.model1.id,
                                  self.model2))

    def test_delete_assert(self):
        with self.assertRaises(AssertionError):
            self.database.delete(None)

    def test_delete(self):
        self.database.post(self.model1.type, self.model1)
        self.assertTrue(self.database.delete(self.model1))
        self.assertIsNone(self.database.get(self.model1.type, self.model1.id))

    def test_get_all(self):
        self.database.backend.clear()
        self.database.post(self.model1.type, self.model1)
        self.database.post(self.model2.type, self.model2)
        # Get the same object
        all_tests = self.database.get_all(self.model1.type)
        self.assertIsInstance(all_tests, list)
        self.assertIn(self.model1, self.database.get_all(self.model1.type))
        self.assertIn(self.model2, self.database.get_all(self.model2.type))

        # Get a noneexisting model
        self.assertIsNone(self.database.get_all('hi'))

    @mock.patch('market.models.DatabaseModel.encode')
    def test_generate_id_on_clash(self, encode_patch):
        encode_patch.return_value = True

        model = DatabaseModel()
        self.database.post(model.type, model)

        model2 = DatabaseModel()
        unique_id = 'unique_id'

        model2.generate_id = Mock()
        model2.generate_id.side_effect = [model.id, unique_id]

        self.database.post(model2.type, model2)

        self.assertEqual(model2.id, unique_id)
        self.assertEqual(model2.generate_id.call_count, 2)