def test_run_cmd(): Input = utlz.namedtuple('Input', 'cmd, timeout=30, max_try=3, num_try=1') def Expected(exitcode, stdout, stderr): return utlz.cmd.CmdResult(exitcode, stdout, stderr, None, None) TestCase = utlz.namedtuple('TestDatum', 'comment, input, expected') test_data = [ TestCase('command as string', Input(cmd='echo foo'), Expected(0, b'foo\n', b'')), TestCase('command as list', Input(cmd=['echo', 'foo']), Expected(0, b'foo\n', b'')), TestCase('exitcode != 0', Input(cmd=['bash', '-c', 'exit 123']), Expected(123, b'', b'')), TestCase('on timeout (no return of cmd => exitcode must be None)', Input('sleep 0.1', timeout=0.01, max_try=1), Expected(None, b'', b'')), TestCase('no timeout', Input('sleep 0.01', timeout=0.1, max_try=1), Expected(0, b'', b'')), ] for test in test_data: res = utlz.cmd.run_cmd(**test.input._asdict()) assert res.stdout == test.expected.stdout assert res.stderr == test.expected.stderr assert res.exitcode == test.expected.exitcode
Log = namedtuple( typename='Log', field_names=[ # each of type: str 'description', 'key', # base-64 encoded, type: str 'url', 'maximum_merge_delay', 'operated_by', # optional infos from *.json 'final_sth=None', 'disqualified_at=None', 'dns_api_endpoint=None', # optional infos from webpage 'known logs' 'contact=None', 'chrome_bug=None', 'notes=None', 'id_b64_non_calculated=None', 'certificate_expiry_range=None', # ChromeStates attribute or None 'chrome_state=None', # TODO add real checks; interact with logs (-> ctlog.py): # True, False, or None 'active=None', # log accepts new entries # True, False, or None 'alive=None', # log answers ], lazy_vals={ 'key_der': lambda self: decode_from_b64(self.key), # type: bytes 'id_der': lambda self: digest_from_b64(self.key), # type: bytes 'id_b64': lambda self: encode_to_b64(self.id_der), # type: str 'pubkey': lambda self: '\n'.join([ # type: str '-----BEGIN PUBLIC KEY-----', text_with_newlines(text=self.key, line_length=64), '-----END PUBLIC KEY-----' ]), 'scts_accepted_by_chrome': lambda self: None if self.chrome_state is None else True if self.chrome_state in [ChromeStates.INCLUDED, ChromeStates.FROZEN] else False, })
Log = namedtuple( typename='Log', field_names=[ # each of type: str 'key', # base-64 encoded, type: str 'log_id', 'mmd', # v1: maximum_merge_delay 'url', # optional ones: 'description=None', 'dns=None', 'temporal_interval=None', 'log_type=None', 'state=None', # JSON-schema has: pending, qualified, usable, readonly, retired, rejected 'operated_by=None', # TODO add real checks; interact with logs (-> ctlog.py): # True, False, or None 'active=None', # log accepts new entries # True, False, or None 'alive=None', # log answers ], lazy_vals={ 'key_der': lambda self: decode_from_b64(self.key), # type: bytes 'log_id_der': lambda self: digest_from_b64(self.key), # type: bytes 'pubkey': lambda self: '\n'.join([ # type: str '-----BEGIN PUBLIC KEY-----', text_with_newlines(text=self.key, line_length=64), '-----END PUBLIC KEY-----' ]), 'scts_accepted_by_chrome': lambda self: None if self.state is None else True if next(iter(self.state)) in [ KnownCTStates.USABLE, KnownCTStates.QUALIFIED, KnownCTStates. READONLY ] else False, })
AddonPackage = utlz.namedtuple( typename='Names', field_names=['module_dir'], lazy_vals={ # eg. 'fabsetup_theno_termdown' 'module_name': lambda self: self.module_dir.rsplit('/', 1)[-1], # eg. 'fabsetup-theno-termdown' 'package_name': lambda self: self.module_name.replace('_', '-'), # would be 'site-packages' when fabsetup is installed as pip package: # 'package_name': lambda self: self.module_dir.rsplit('/', 2)[-2], # eg. '/home/theno/.fabsetup-addon-repos/fabsetup-theno-termdown' 'package_dir': lambda self: dirname(self.module_dir), # '/home/theno/.fabsetup-addon-repos/fabsetup-theno-termdown/fabsetup_theno_termdown/files' 'default_files_basedir': lambda self: join(self.module_dir, 'files'), # eg. '/home/theno/.fabsetup-custom/fabsetup-theno-termdown' 'custom_dir': lambda self: join(FABSETUP_CUSTOM_DIR, self.package_name), # eg. '/home/theno/.fabsetup-custom/fabsetup-theno-termdown/config.py' 'custom_config': lambda self: join(self.custom_dir, 'config.py'), # eg. '/home/theno/.fabsetup-custom/fabsetup-theno-termdown/files' 'custom_files_basedir': lambda self: join(FABSETUP_CUSTOM_DIR, self.package_name, 'files'), # eg. '/home/theno/.fabsetup-downloads/fabsetup-theno-termdown' 'downloads_basedir': lambda self: join(FABSETUP_DOWNLOADS_DIR, self.package_name), })
return scts TlsHandshakeResult = namedtuple( typename='TlsHandshakeResult', field_names=[ 'ee_cert_der', # (bytes) 'issuer_cert_der', # (bytes) 'more_issuer_cert_der_candidates', # [(bytes), ...] 'ocsp_resp_der', # (bytes) 'tls_ext_18_tdf', # (bytes) 'err', # (str) ], lazy_vals={ 'ee_cert': lambda self: EndEntityCert(self.ee_cert_der), 'issuer_cert': lambda self: IssuerCert(self.issuer_cert_der), 'more_issuer_cert_candidates': lambda self: [ IssuerCert(cert_der) for cert_der in self.more_issuer_cert_der_candidates], 'scts_by_cert': lambda self: scts_from_cert(self.ee_cert_der), 'scts_by_ocsp': lambda self: scts_from_ocsp_resp(self.ocsp_resp_der), 'scts_by_tls': lambda self: scts_from_tls_ext_18(self.tls_ext_18_tdf), } ) def create_context(scts_tls, scts_ocsp, timeout): '''
copy = copy_pyasn1_instance(tbscert) copy['extensions'] = without_ct_extensions return copy TbsCert = namedtuple( typename='TbsCert', field_names=[ 'pyasn1', ], lazy_vals={ 'der': lambda self: der_encoder(self.pyasn1), 'len': lambda self: len(self.der), 'lens': lambda self: struct.unpack('!4B', struct.pack('!I', self.len)), # cf. https://tools.ietf.org/html/rfc6962#section-3.2 <1..2^24-1> 'len1': lambda self: self.lens[1], 'len2': lambda self: self.lens[2], 'len3': lambda self: self.lens[3], 'without_ct_extensions': lambda self: TbsCert(tbscert_without_ct_extensions(self.pyasn1)), }) EndEntityCert = namedtuple( typename='EndEntityCert', field_names=[ 'der',