From f09bc4dd77f36d8e50e5171d5fa1c9c2212e618c Mon Sep 17 00:00:00 2001 From: Tomas Susanka Date: Thu, 3 Oct 2019 12:01:27 +0000 Subject: [PATCH 1/3] tools/issues: fix weights and add auth --- tools/github_issues_to_csv.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/tools/github_issues_to_csv.py b/tools/github_issues_to_csv.py index cb81a1d377..5737f2f831 100644 --- a/tools/github_issues_to_csv.py +++ b/tools/github_issues_to_csv.py @@ -8,7 +8,8 @@ import csv from getpass import getpass import requests -auth = None +auth_id = None +auth_secret = None PRIORITIES = ("P1", "P2", "P3", "P4") SEVERITIES = ("S1", "S2", "S3", "S4") @@ -29,7 +30,7 @@ def write_issues(r, csvout): priority = l["name"] elif l["name"][:2] in SEVERITIES: severity = l["name"] - elif l["name"][:2] in WEIGHTS: + elif l["name"] in WEIGHTS: weight = l["name"][1:] if weight == "1/2": weight = "0.5" @@ -47,8 +48,11 @@ def write_issues(r, csvout): def get_issues(name): """Requests issues from GitHub API and writes to CSV file.""" - url = 'https://api.github.com/repos/{}/issues?state=all'.format(name) - r = requests.get(url, auth=auth) + if auth_secret: + url = 'https://api.github.com/repos/{}/issues?state=all&client_id={}&client_secret={}'.format(name, auth_id, auth_secret) + else: + url = 'https://api.github.com/repos/{}/issues?state=all'.format(name) + r = requests.get(url) csvfilename = '{}-issues.csv'.format(name.replace('/', '-')) with open(csvfilename, 'w', newline='') as csvfile: @@ -65,7 +69,7 @@ def get_issues(name): pages = {rel[6:-1]: url[url.index('<')+1:-1] for url, rel in (link.split(';') for link in r.headers['link'].split(','))} - r = requests.get(pages['next'], auth=auth) + r = requests.get(pages['next']) write_issues(r, csvout) if pages['next'] == pages['last']: break From 861e999425800b6fa19dfe17028928f9dd67a698 Mon Sep 17 00:00:00 2001 From: matejcik Date: Wed, 2 Oct 2019 16:07:43 +0200 Subject: [PATCH 2/3] core: draft unit test for process_slip39 --- core/tests/mock.py | 48 +++++++++++++++++++ core/tests/storage.py | 42 ++++++++++++++++ .../test_apps.management.recovery_device.py | 38 +++++++++++++++ 3 files changed, 128 insertions(+) create mode 100644 core/tests/mock.py create mode 100644 core/tests/storage.py create mode 100644 core/tests/test_apps.management.recovery_device.py diff --git a/core/tests/mock.py b/core/tests/mock.py new file mode 100644 index 0000000000..f5bd260083 --- /dev/null +++ b/core/tests/mock.py @@ -0,0 +1,48 @@ +if False: + from typing import Any + + +class Mock: + def __init__(self, return_value: Any = None, raises: BaseException = None) -> None: + self.attrs = {} + self.calls = [] + self.return_value = return_value + self.raises = raises + + def __getattr__(self, key: str) -> Any: + self.attrs.setdefault(key, Mock()) + return self.attrs[key] + + def __setattr__(self, name: str, value: Any) -> Any: + self.attrs[name] = value + return value + + def __call__(self, *args, **kwargs) -> Any: + self.calls.append((args, kwargs)) + if self.raises is not None: + raise self.raises + return self.return_value + + +class patch: + MOCK_OBJECT = object() + NO_VALUE = object() + + def __init__(self, obj: Any, attr: str, value: Any = MOCK_OBJECT) -> None: + self.obj = obj + self.attr = attr + self.value = value + self.orig_value = self.NO_VALUE + + def __enter__(self): + if hasattr(self.obj, self.attr): + self.orig_value = getattr(self.obj, self.attr) + + patch_value = self.value if self.value is not self.MOCK_OBJECT else Mock() + setattr(self.obj, self.attr, patch_value) + + def __exit__(self, exc_type, exc_value, tb): + if self.orig_value is self.NO_VALUE: + delattr(self.obj, self.attr) + else: + setattr(self.obj, self.attr, self.orig_value) diff --git a/core/tests/storage.py b/core/tests/storage.py new file mode 100644 index 0000000000..d97bc32ffe --- /dev/null +++ b/core/tests/storage.py @@ -0,0 +1,42 @@ +from mock import patch + +import apps.common.storage.common + +class MockStorage: + PATCH_METHODS = ("get", "set", "delete") + + def __init__(self): + self.namespace = {} + self.patches = [ + patch(apps.common.storage.common, method, getattr(self, method)) + for method in self.PATCH_METHODS + ] + + def set(self, app: int, key: int, data: bytes, public: bool = False) -> None: + self.namespace.setdefault(app, {}) + self.namespace[app][key] = data + + def get(self, app: int, key: int, public: bool = False) -> Optional[bytes]: + self.namespace.setdefault(app, {}) + return self.namespace[app].get(key) + + def delete(self, app: int, key: int, public: bool = False) -> None: + self.namespace.setdefault(app, {}) + self.namespace[app].pop(key, None) + + def __enter__(self): + for patch in self.patches: + patch.__enter__() + return self + + def __exit__(self, exc_type, exc_value, tb): + for patch in self.patches: + patch.__exit__(exc_type, exc_value, tb) + + +def mock_storage(func): + def inner(*args, **kwargs): + with MockStorage(): + return func(*args, **kwargs) + + return inner diff --git a/core/tests/test_apps.management.recovery_device.py b/core/tests/test_apps.management.recovery_device.py new file mode 100644 index 0000000000..86db4dbc58 --- /dev/null +++ b/core/tests/test_apps.management.recovery_device.py @@ -0,0 +1,38 @@ +from common import * +from storage import mock_storage + +import apps.common.storage.recovery +from apps.common import storage +from apps.management.recovery_device.recover import process_slip39 + +MNEMONIC_SLIP39_BASIC_20_3of6 = [ + "extra extend academic bishop cricket bundle tofu goat apart victim enlarge program behavior permit course armed jerky faint language modern", + "extra extend academic acne away best indicate impact square oasis prospect painting voting guest either argue username racism enemy eclipse", + "extra extend academic arcade born dive legal hush gross briefing talent drug much home firefly toxic analysis idea umbrella slice", +] +# Shamir shares (128 bits, 2 groups from 1 of 1, 1 of 1, 3 of 5, 2 of 6) +MNEMONIC_SLIP39_ADVANCED_20 = [ + "eraser senior beard romp adorn nuclear spill corner cradle style ancient family general leader ambition exchange unusual garlic promise voice", + "eraser senior ceramic snake clay various huge numb argue hesitate auction category timber browser greatest hanger petition script leaf pickup", + "eraser senior ceramic shaft dynamic become junior wrist silver peasant force math alto coal amazing segment yelp velvet image paces", + "eraser senior ceramic round column hawk trust auction smug shame alive greatest sheriff living perfect corner chest sled fumes adequate", +] +# Shamir shares (256 bits, 2 groups from 1 of 1, 1 of 1, 3 of 5, 2 of 6): +MNEMONIC_SLIP39_ADVANCED_33 = [ + "wildlife deal beard romp alcohol space mild usual clothes union nuclear testify course research heat listen task location thank hospital slice smell failure fawn helpful priest ambition average recover lecture process dough stadium", + "wildlife deal acrobat romp anxiety axis starting require metric flexible geology game drove editor edge screw helpful have huge holy making pitch unknown carve holiday numb glasses survive already tenant adapt goat fangs", +] + + +class TestSlip39(unittest.TestCase): + @mock_storage + def test_process_slip39(self): + storage.recovery.set_in_progress(True) + words = MNEMONIC_SLIP39_BASIC_20_3of6[0] + secret, share = process_slip39(words) + self.assertIsNone(secret) + self.assertEqual(share.group_count, storage.recovery.get_slip39_group_count()) + + +if __name__ == "__main__": + unittest.main() From 737ebeec1c8ba91c7d5d78c598a6cabd7e4785e8 Mon Sep 17 00:00:00 2001 From: Tomas Susanka Date: Fri, 4 Oct 2019 09:37:44 +0200 Subject: [PATCH 3/3] ci: add 'retry' to flaky tests (Monero and U2F) --- ci/test.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ci/test.yml b/ci/test.yml index c654982799..8bc87e10cb 100644 --- a/ci/test.yml +++ b/ci/test.yml @@ -62,6 +62,7 @@ core unix btconly device test: core unix monero test: stage: test <<: *only_changes_core + retry: 2 # see #405 dependencies: - core unix frozen regular build script: @@ -71,6 +72,7 @@ core unix monero test: core unix u2f test: stage: test <<: *only_changes_core + retry: 2 # see #596 dependencies: - core unix frozen regular build script: