summaryrefslogtreecommitdiff
path: root/tests/benchmarks/test_crypto.py
blob: 3be447a5f7241cae11f74c12a342902cd0f413ec (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
"""
Benchmarks for crypto operations.
If you don't want to stress your local machine too much, you can pass the
SIZE_LIMT environment variable.

For instance, to keep the maximum payload at 1MB:

SIZE_LIMIT=1E6 py.test -s tests/perf/test_crypto.py
"""
import pytest
import os
import json
from uuid import uuid4

from leap.soledad.common.document import SoledadDocument
from leap.soledad.client import _crypto

LIMIT = int(float(os.environ.get('SIZE_LIMIT', 50 * 1000 * 1000)))


def create_doc_encryption(size):
    @pytest.mark.benchmark(group="test_crypto_encrypt_doc")
    @pytest.inlineCallbacks
    def test_doc_encryption(soledad_client, txbenchmark, payload):
        """
        Encrypt a document of a given size.
        """
        crypto = soledad_client()._crypto

        DOC_CONTENT = {'payload': payload(size)}
        doc = SoledadDocument(
            doc_id=uuid4().hex, rev='rev',
            json=json.dumps(DOC_CONTENT))

        yield txbenchmark(crypto.encrypt_doc, doc)
    return test_doc_encryption


# TODO this test is really bullshit, because it's still including
# the json serialization.

def create_doc_decryption(size):
    @pytest.inlineCallbacks
    @pytest.mark.benchmark(group="test_crypto_decrypt_doc")
    def test_doc_decryption(soledad_client, txbenchmark, payload):
        """
        Decrypt a document of a given size.
        """
        crypto = soledad_client()._crypto

        DOC_CONTENT = {'payload': payload(size)}
        doc = SoledadDocument(
            doc_id=uuid4().hex, rev='rev',
            json=json.dumps(DOC_CONTENT))

        encrypted_doc = yield crypto.encrypt_doc(doc)
        doc.set_json(encrypted_doc)

        yield txbenchmark(crypto.decrypt_doc, doc)
    return test_doc_decryption


def create_raw_encryption(size):
    @pytest.mark.benchmark(group="test_crypto_raw_encrypt")
    def test_raw_encrypt(monitored_benchmark, payload):
        """
        Encrypt raw payload using default mode from crypto module.
        """
        key = payload(32)
        monitored_benchmark(_crypto.encrypt_sym, payload(size), key)
    return test_raw_encrypt


def create_raw_decryption(size):
    @pytest.mark.benchmark(group="test_crypto_raw_decrypt")
    def test_raw_decrypt(monitored_benchmark, payload):
        """
        Decrypt raw payload using default mode from crypto module.
        """
        key = payload(32)
        iv, ciphertext = _crypto.encrypt_sym(payload(size), key)
        monitored_benchmark(_crypto.decrypt_sym, ciphertext, key, iv)
    return test_raw_decrypt


# Create the TESTS in the global namespace, they'll be picked by the benchmark
# plugin.

encryption_tests = [
    ('10k', 1E4),
    ('100k', 1E5),
    ('500k', 5E5),
    ('1M', 1E6),
    ('10M', 1E7),
    ('50M', 5E7),
]

for name, size in encryption_tests:
    if size < LIMIT:
        sz = int(size)
        globals()['test_encrypt_doc_' + name] = create_doc_encryption(sz)
        globals()['test_decrypt_doc_' + name] = create_doc_decryption(sz)


for name, size in encryption_tests:
    if size < LIMIT:
        sz = int(size)
        globals()['test_encrypt_raw_' + name] = create_raw_encryption(sz)
        globals()['test_decrypt_raw_' + name] = create_raw_decryption(sz)