tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

test_actions_util.py (5598B)


      1 # This Source Code Form is subject to the terms of the Mozilla Public
      2 # License, v. 2.0. If a copy of the MPL was not distributed with this
      3 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
      4 
      5 
      6 import unittest
      7 from pprint import pprint
      8 from unittest.mock import patch
      9 
     10 import pytest
     11 from mozunit import MockedOpen, main
     12 from taskgraph import create
     13 from taskgraph.util import json, taskcluster
     14 
     15 from gecko_taskgraph import actions
     16 from gecko_taskgraph.actions.util import combine_task_graph_files, relativize_datestamps
     17 from gecko_taskgraph.decision import read_artifact
     18 
     19 TASK_DEF = {
     20    "created": "2017-10-10T18:33:03.460Z",
     21    # note that this is not an even number of seconds off!
     22    "deadline": "2017-10-11T18:33:03.461Z",
     23    "dependencies": [],
     24    "expires": "2018-10-10T18:33:04.461Z",
     25    "payload": {
     26        "artifacts": {
     27            "public": {
     28                "expires": "2018-10-10T18:33:03.463Z",
     29                "path": "/builds/worker/artifacts",
     30                "type": "directory",
     31            },
     32        },
     33        "maxRunTime": 1800,
     34    },
     35 }
     36 
     37 
     38 @pytest.fixture(scope="module", autouse=True)
     39 def enable_test_mode():
     40    create.testing = True
     41    taskcluster.testing = True
     42 
     43 
     44 class TestRelativize(unittest.TestCase):
     45    def test_relativize(self):
     46        rel = relativize_datestamps(TASK_DEF)
     47        import pprint
     48 
     49        pprint.pprint(rel)
     50        assert rel["created"] == {"relative-datestamp": "0 seconds"}
     51        assert rel["deadline"] == {"relative-datestamp": "86400 seconds"}
     52        assert rel["expires"] == {"relative-datestamp": "31536001 seconds"}
     53        assert rel["payload"]["artifacts"]["public"]["expires"] == {
     54            "relative-datestamp": "31536000 seconds"
     55        }
     56 
     57 
     58 class TestCombineTaskGraphFiles(unittest.TestCase):
     59    def test_no_suffixes(self):
     60        with MockedOpen({}):
     61            combine_task_graph_files([])
     62            self.assertRaises(Exception, open("artifacts/to-run.json"))
     63 
     64    @patch("gecko_taskgraph.actions.util.rename_artifact")
     65    def test_one_suffix(self, rename_artifact):
     66        combine_task_graph_files(["0"])
     67        rename_artifact.assert_any_call("task-graph-0.json", "task-graph.json")
     68        rename_artifact.assert_any_call(
     69            "label-to-taskid-0.json", "label-to-taskid.json"
     70        )
     71        rename_artifact.assert_any_call("to-run-0.json", "to-run.json")
     72 
     73    def test_several_suffixes(self):
     74        files = {
     75            "artifacts/task-graph-0.json": json.dumps({"taska": {}}),
     76            "artifacts/label-to-taskid-0.json": json.dumps({"taska": "TASKA"}),
     77            "artifacts/to-run-0.json": json.dumps(["taska"]),
     78            "artifacts/task-graph-1.json": json.dumps({"taskb": {}}),
     79            "artifacts/label-to-taskid-1.json": json.dumps({"taskb": "TASKB"}),
     80            "artifacts/to-run-1.json": json.dumps(["taskb"]),
     81        }
     82        with MockedOpen(files):
     83            combine_task_graph_files(["0", "1"])
     84            self.assertEqual(
     85                read_artifact("task-graph.json"),
     86                {
     87                    "taska": {},
     88                    "taskb": {},
     89                },
     90            )
     91            self.assertEqual(
     92                read_artifact("label-to-taskid.json"),
     93                {
     94                    "taska": "TASKA",
     95                    "taskb": "TASKB",
     96                },
     97            )
     98            self.assertEqual(
     99                sorted(read_artifact("to-run.json")),
    100                [
    101                    "taska",
    102                    "taskb",
    103                ],
    104            )
    105 
    106 
    107 def is_subset(subset, superset):
    108    if isinstance(subset, dict):
    109        return all(
    110            key in superset and is_subset(val, superset[key])
    111            for key, val in subset.items()
    112        )
    113 
    114    if isinstance(subset, list) or isinstance(subset, set):
    115        return all(
    116            any(is_subset(subitem, superitem) for superitem in superset)
    117            for subitem in subset
    118        )
    119 
    120    if isinstance(subset, str):
    121        return subset in superset
    122 
    123    # assume that subset is a plain value if none of the above match
    124    return subset == superset
    125 
    126 
    127 @pytest.mark.parametrize(
    128    "task_def,expected",
    129    [
    130        pytest.param(
    131            {"tags": {"kind": "decision-task"}},
    132            {
    133                "hookPayload": {
    134                    "decision": {
    135                        "action": {"cb_name": "retrigger-decision"},
    136                    },
    137                },
    138            },
    139            id="retrigger_decision",
    140        ),
    141        pytest.param(
    142            {"tags": {"action": "backfill-task"}},
    143            {
    144                "hookPayload": {
    145                    "decision": {
    146                        "action": {"cb_name": "retrigger-decision"},
    147                    },
    148                },
    149            },
    150            id="retrigger_backfill",
    151        ),
    152    ],
    153 )
    154 def test_extract_applicable_action(
    155    responses, monkeypatch, actions_json, task_def, expected
    156 ):
    157    actions.util.get_task_definition.cache_clear()
    158    base_url = "https://taskcluster"
    159    decision_task_id = "dddd"
    160    task_id = "tttt"
    161 
    162    monkeypatch.setenv("TASK_ID", task_id)
    163    monkeypatch.setenv("TASKCLUSTER_ROOT_URL", base_url)
    164    monkeypatch.setenv("TASKCLUSTER_PROXY_URL", base_url)
    165    responses.add(
    166        responses.GET,
    167        f"{base_url}/api/queue/v1/task/{task_id}",
    168        status=200,
    169        json=task_def,
    170    )
    171    action = actions.util._extract_applicable_action(
    172        actions_json, "retrigger", decision_task_id, task_id
    173    )
    174    pprint(action, indent=2)
    175    assert is_subset(expected, action)
    176 
    177 
    178 if __name__ == "__main__":
    179    main()