quickjs-tart

quickjs-based runtime for wallet-core logic
Log | Files | Refs | README | LICENSE

tls_test_case.py (3940B)


      1 """Library for constructing an Mbed TLS ssl-opt test case.
      2 """
      3 
      4 # Copyright The Mbed TLS Contributors
      5 # SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
      6 
      7 import enum
      8 import re
      9 from typing import List
     10 
     11 from . import typing_util
     12 
     13 
     14 class TestCase:
     15     """Data about an ssl-opt test case."""
     16     #pylint: disable=too-few-public-methods
     17 
     18     def __init__(self, description: str) -> None:
     19         # List of shell snippets to call before run_test, typically
     20         # calls to requires_xxx functions.
     21         self.requirements = [] #type: List[str]
     22         # Test case description (first argument to run_test).
     23         self.description = description
     24         # Client command line.
     25         # This will be placed directly inside double quotes in the shell script.
     26         self.client = '$P_CLI'
     27         # Server command line.
     28         # This will be placed directly inside double quotes in the shell script.
     29         self.server = '$P_SRV'
     30         # Expected client exit code.
     31         self.exit_code = 0
     32 
     33         # Note that all patterns matched in the logs are in BRE
     34         # (Basic Regular Expression) syntax, more precisely in the BRE
     35         # dialect that is the default for GNU grep. The main difference
     36         # with Python regular expressions is that the operators for
     37         # grouping `\(...\)`, alternation `x\|y`, option `x\?`,
     38         # one-or-more `x\+` and repetition ranges `x\{M,N\}` must be
     39         # preceded by a backslash. The characters `()|?+{}` stand for
     40         # themselves.
     41 
     42         # BRE for text that must be present in the client log (run_test -c).
     43         self.wanted_client_patterns = [] #type: List[str]
     44         # BRE for text that must be present in the server log (run_test -s).
     45         self.wanted_server_patterns = [] #type: List[str]
     46         # BRE for text that must not be present in the client log (run_test -C).
     47         self.forbidden_client_patterns = [] #type: List[str]
     48         # BRE for text that must not be present in the server log (run_test -S).
     49         self.forbidden_server_patterns = [] #type: List[str]
     50 
     51     @staticmethod
     52     def _quote(raw: str) -> str:
     53         """Quote the given string for sh.
     54 
     55         Use double quotes, because that's currently the norm in ssl-opt.sh.
     56         """
     57         return '"' + re.sub(r'([$"\\`])', r'\\\1', raw) + '"'
     58 
     59     def write(self, out: typing_util.Writable) -> None:
     60         """Write the test case to the specified file."""
     61         for req in self.requirements:
     62             out.write(req + '\n')
     63         out.write(f'run_test    {self._quote(self.description)} \\\n')
     64         out.write(f'            "{self.server}" \\\n')
     65         out.write(f'            "{self.client}" \\\n')
     66         out.write(f'            {self.exit_code}')
     67         for pat in self.wanted_server_patterns:
     68             out.write(' \\\n            -s ' + self._quote(pat))
     69         for pat in self.forbidden_server_patterns:
     70             out.write(' \\\n            -S ' + self._quote(pat))
     71         for pat in self.wanted_client_patterns:
     72             out.write(' \\\n            -c ' + self._quote(pat))
     73         for pat in self.forbidden_client_patterns:
     74             out.write(' \\\n            -C ' + self._quote(pat))
     75         out.write('\n\n')
     76 
     77 
     78 class Side(enum.Enum):
     79     CLIENT = 0
     80     SERVER = 1
     81 
     82 class Version(enum.Enum):
     83     """TLS protocol version.
     84 
     85     This class doesn't know about DTLS yet.
     86     """
     87 
     88     TLS12 = 2
     89     TLS13 = 3
     90 
     91     def force_version(self) -> str:
     92         """Argument to pass to ssl_client2 or ssl_server2 to force this version."""
     93         return f'force_version=tls1{self.value}'
     94 
     95     def openssl_option(self) -> str:
     96         """Option to pass to openssl s_client or openssl s_server to select this version."""
     97         return f'-tls1_{self.value}'
     98 
     99     def requires_command(self) -> str:
    100         """Command to require this protocol version in an ssl-opt.sh test case."""
    101         return 'requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_' + str(self.value)