We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Support for codecoverage when running Python tests
Avocado doesn't have a documented and/or supported way for generating code coverage information when running Python based tests.

The first objective is to drop the use of the custom `selftests/run_coverage` script and the additional job, in favor of reusing one already existing CI job with Avocado:

 * running code coverage tools
 * keeping the information
 * pushing the information

Even though Python based tests and code coverage is the primary goal of this issue, it's probable that the solution will be about providing a flexible way to add a "wrapper" of sorts before the actual execution of tests.
 

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `avocado/core/runners/avocado_instrumented.py`
Content:
```
1 import multiprocessing
2 import tempfile
3 import time
4 import traceback
5 
6 from avocado.core import nrunner
7 from avocado.core.runners.utils import messages
8 from avocado.core.test import TestID
9 from avocado.core.tree import TreeNodeEnvOnly
10 from avocado.core.utils import loader
11 from avocado.core.varianter import is_empty_variant
12 
13 
14 class AvocadoInstrumentedTestRunner(nrunner.BaseRunner):
15     """
16     Runner for Avocado INSTRUMENTED tests
17 
18     Runnable attributes usage:
19 
20      * uri: path to a test file, combined with an Avocado.Test
21        inherited class name and method.  The test file path and
22        class and method names should be separated by a ":".  One
23        example of a valid uri is "mytest.py:Class.test_method".
24 
25      * args: not used
26     """
27     DEFAULT_TIMEOUT = 86400
28 
29     @staticmethod
30     def _create_params(runnable):
31         """Create params for the test"""
32         if runnable.variant is None:
33             return None
34 
35         # rebuild the variant tree
36         variant_tree_nodes = [TreeNodeEnvOnly(path, env) for path, env
37                               in runnable.variant['variant']]
38 
39         if not is_empty_variant(variant_tree_nodes):
40             tree_nodes = variant_tree_nodes
41             paths = runnable.variant['paths']
42             return tree_nodes, paths
43 
44     @staticmethod
45     def _run_avocado(runnable, queue):
46         try:
47             # This assumes that a proper resolution (see resolver module)
48             # was performed, and that a URI contains:
49             # 1) path to python module
50             # 2) class
51             # 3) method
52             #
53             # To be defined: if the resolution uri should be composed like
54             # this, or broken down and stored into other data fields
55             module_path, klass_method = runnable.uri.split(':', 1)
56 
57             klass, method = klass_method.split('.', 1)
58 
59             params = AvocadoInstrumentedTestRunner._create_params(runnable)
60             result_dir = (runnable.output_dir or
61                           tempfile.mkdtemp(prefix=".avocado-task"))
62             test_factory = [klass,
63                             {'name': TestID(1, runnable.uri),
64                              'methodName': method,
65                              'config': runnable.config,
66                              'modulePath': module_path,
67                              'params': params,
68                              'tags': runnable.tags,
69                              'run.results_dir': result_dir,
70                              }]
71 
72             messages.start_logging(runnable.config, queue)
73             instance = loader.load_test(test_factory)
74             early_state = instance.get_state()
75             early_state['type'] = "early_state"
76             queue.put(early_state)
77             instance.run_avocado()
78             state = instance.get_state()
79             fail_reason = state.get('fail_reason')
80             queue.put(messages.WhiteboardMessage.get(state['whiteboard']))
81             queue.put(messages.FinishedMessage.get(state['status'].lower(),
82                                                    fail_reason=fail_reason))
83         except Exception as e:
84             queue.put(messages.StderrMessage.get(traceback.format_exc()))
85             queue.put(messages.FinishedMessage.get('error', fail_reason=str(e)))
86 
87     def run(self):
88         yield messages.StartedMessage.get()
89         try:
90             queue = multiprocessing.SimpleQueue()
91             process = multiprocessing.Process(target=self._run_avocado,
92                                               args=(self.runnable, queue))
93 
94             process.start()
95 
96             time_started = time.monotonic()
97 
98             timeout = float(self.DEFAULT_TIMEOUT)
99             most_current_execution_state_time = None
100             while True:
101                 time.sleep(nrunner.RUNNER_RUN_CHECK_INTERVAL)
102                 now = time.monotonic()
103                 if queue.empty():
104                     if most_current_execution_state_time is not None:
105                         next_execution_state_mark = (most_current_execution_state_time +
106                                                      nrunner.RUNNER_RUN_STATUS_INTERVAL)
107                     if (most_current_execution_state_time is None or
108                             now > next_execution_state_mark):
109                         most_current_execution_state_time = now
110                         yield messages.RunningMessage.get()
111                     if (now - time_started) > timeout:
112                         process.terminate()
113                         yield messages.FinishedMessage.get('interrupted',
114                                                            'timeout')
115                         break
116                 else:
117                     message = queue.get()
118                     if message.get('type') == 'early_state':
119                         timeout = float(message.get('timeout') or
120                                         self.DEFAULT_TIMEOUT)
121                     else:
122                         yield message
123                     if message.get('status') == 'finished':
124                         break
125         except Exception as e:
126             yield messages.StderrMessage.get(traceback.format_exc())
127             yield messages.FinishedMessage.get('error', fail_reason=str(e))
128 
129 
130 class RunnerApp(nrunner.BaseRunnerApp):
131     PROG_NAME = 'avocado-runner-avocado-instrumented'
132     PROG_DESCRIPTION = 'nrunner application for avocado-instrumented tests'
133     RUNNABLE_KINDS_CAPABLE = {
134         'avocado-instrumented': AvocadoInstrumentedTestRunner
135     }
136 
137 
138 def main():
139     nrunner.main(RunnerApp)
140 
141 
142 if __name__ == '__main__':
143     main()
144
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/avocado/core/runners/avocado_instrumented.py b/avocado/core/runners/avocado_instrumented.py
--- a/avocado/core/runners/avocado_instrumented.py
+++ b/avocado/core/runners/avocado_instrumented.py
@@ -1,4 +1,5 @@
 import multiprocessing
+import os
 import tempfile
 import time
 import traceback
@@ -70,11 +71,22 @@
                              }]
 
             messages.start_logging(runnable.config, queue)
+
+            if 'COVERAGE_RUN' in os.environ:
+                from coverage import Coverage
+                coverage = Coverage()
+                coverage.start()
+
             instance = loader.load_test(test_factory)
             early_state = instance.get_state()
             early_state['type'] = "early_state"
             queue.put(early_state)
             instance.run_avocado()
+
+            if 'COVERAGE_RUN' in os.environ:
+                coverage.stop()
+                coverage.save()
+
             state = instance.get_state()
             fail_reason = state.get('fail_reason')
             queue.put(messages.WhiteboardMessage.get(state['whiteboard']))

{"golden_diff": "diff --git a/avocado/core/runners/avocado_instrumented.py b/avocado/core/runners/avocado_instrumented.py\n--- a/avocado/core/runners/avocado_instrumented.py\n+++ b/avocado/core/runners/avocado_instrumented.py\n@@ -1,4 +1,5 @@\n import multiprocessing\n+import os\n import tempfile\n import time\n import traceback\n@@ -70,11 +71,22 @@\n                              }]\n \n             messages.start_logging(runnable.config, queue)\n+\n+            if 'COVERAGE_RUN' in os.environ:\n+                from coverage import Coverage\n+                coverage = Coverage()\n+                coverage.start()\n+\n             instance = loader.load_test(test_factory)\n             early_state = instance.get_state()\n             early_state['type'] = \"early_state\"\n             queue.put(early_state)\n             instance.run_avocado()\n+\n+            if 'COVERAGE_RUN' in os.environ:\n+                coverage.stop()\n+                coverage.save()\n+\n             state = instance.get_state()\n             fail_reason = state.get('fail_reason')\n             queue.put(messages.WhiteboardMessage.get(state['whiteboard']))\n", "issue": "Support for codecoverage when running Python tests\nAvocado doesn't have a documented and/or supported way for generating code coverage information when running Python based tests.\r\n\r\nThe first objective is to drop the use of the custom `selftests/run_coverage` script and the additional job, in favor of reusing one already existing CI job with Avocado:\r\n\r\n * running code coverage tools\r\n * keeping the information\r\n * pushing the information\r\n\r\nEven though Python based tests and code coverage is the primary goal of this issue, it's probable that the solution will be about providing a flexible way to add a \"wrapper\" of sorts before the actual execution of tests.\r\n \n", "before_files": [{"content": "import multiprocessing\nimport tempfile\nimport time\nimport traceback\n\nfrom avocado.core import nrunner\nfrom avocado.core.runners.utils import messages\nfrom avocado.core.test import TestID\nfrom avocado.core.tree import TreeNodeEnvOnly\nfrom avocado.core.utils import loader\nfrom avocado.core.varianter import is_empty_variant\n\n\nclass AvocadoInstrumentedTestRunner(nrunner.BaseRunner):\n    \"\"\"\n    Runner for Avocado INSTRUMENTED tests\n\n    Runnable attributes usage:\n\n     * uri: path to a test file, combined with an Avocado.Test\n       inherited class name and method.  The test file path and\n       class and method names should be separated by a \":\".  One\n       example of a valid uri is \"mytest.py:Class.test_method\".\n\n     * args: not used\n    \"\"\"\n    DEFAULT_TIMEOUT = 86400\n\n    @staticmethod\n    def _create_params(runnable):\n        \"\"\"Create params for the test\"\"\"\n        if runnable.variant is None:\n            return None\n\n        # rebuild the variant tree\n        variant_tree_nodes = [TreeNodeEnvOnly(path, env) for path, env\n                              in runnable.variant['variant']]\n\n        if not is_empty_variant(variant_tree_nodes):\n            tree_nodes = variant_tree_nodes\n            paths = runnable.variant['paths']\n            return tree_nodes, paths\n\n    @staticmethod\n    def _run_avocado(runnable, queue):\n        try:\n            # This assumes that a proper resolution (see resolver module)\n            # was performed, and that a URI contains:\n            # 1) path to python module\n            # 2) class\n            # 3) method\n            #\n            # To be defined: if the resolution uri should be composed like\n            # this, or broken down and stored into other data fields\n            module_path, klass_method = runnable.uri.split(':', 1)\n\n            klass, method = klass_method.split('.', 1)\n\n            params = AvocadoInstrumentedTestRunner._create_params(runnable)\n            result_dir = (runnable.output_dir or\n                          tempfile.mkdtemp(prefix=\".avocado-task\"))\n            test_factory = [klass,\n                            {'name': TestID(1, runnable.uri),\n                             'methodName': method,\n                             'config': runnable.config,\n                             'modulePath': module_path,\n                             'params': params,\n                             'tags': runnable.tags,\n                             'run.results_dir': result_dir,\n                             }]\n\n            messages.start_logging(runnable.config, queue)\n            instance = loader.load_test(test_factory)\n            early_state = instance.get_state()\n            early_state['type'] = \"early_state\"\n            queue.put(early_state)\n            instance.run_avocado()\n            state = instance.get_state()\n            fail_reason = state.get('fail_reason')\n            queue.put(messages.WhiteboardMessage.get(state['whiteboard']))\n            queue.put(messages.FinishedMessage.get(state['status'].lower(),\n                                                   fail_reason=fail_reason))\n        except Exception as e:\n            queue.put(messages.StderrMessage.get(traceback.format_exc()))\n            queue.put(messages.FinishedMessage.get('error', fail_reason=str(e)))\n\n    def run(self):\n        yield messages.StartedMessage.get()\n        try:\n            queue = multiprocessing.SimpleQueue()\n            process = multiprocessing.Process(target=self._run_avocado,\n                                              args=(self.runnable, queue))\n\n            process.start()\n\n            time_started = time.monotonic()\n\n            timeout = float(self.DEFAULT_TIMEOUT)\n            most_current_execution_state_time = None\n            while True:\n                time.sleep(nrunner.RUNNER_RUN_CHECK_INTERVAL)\n                now = time.monotonic()\n                if queue.empty():\n                    if most_current_execution_state_time is not None:\n                        next_execution_state_mark = (most_current_execution_state_time +\n                                                     nrunner.RUNNER_RUN_STATUS_INTERVAL)\n                    if (most_current_execution_state_time is None or\n                            now > next_execution_state_mark):\n                        most_current_execution_state_time = now\n                        yield messages.RunningMessage.get()\n                    if (now - time_started) > timeout:\n                        process.terminate()\n                        yield messages.FinishedMessage.get('interrupted',\n                                                           'timeout')\n                        break\n                else:\n                    message = queue.get()\n                    if message.get('type') == 'early_state':\n                        timeout = float(message.get('timeout') or\n                                        self.DEFAULT_TIMEOUT)\n                    else:\n                        yield message\n                    if message.get('status') == 'finished':\n                        break\n        except Exception as e:\n            yield messages.StderrMessage.get(traceback.format_exc())\n            yield messages.FinishedMessage.get('error', fail_reason=str(e))\n\n\nclass RunnerApp(nrunner.BaseRunnerApp):\n    PROG_NAME = 'avocado-runner-avocado-instrumented'\n    PROG_DESCRIPTION = 'nrunner application for avocado-instrumented tests'\n    RUNNABLE_KINDS_CAPABLE = {\n        'avocado-instrumented': AvocadoInstrumentedTestRunner\n    }\n\n\ndef main():\n    nrunner.main(RunnerApp)\n\n\nif __name__ == '__main__':\n    main()\n", "path": "avocado/core/runners/avocado_instrumented.py"}], "after_files": [{"content": "import multiprocessing\nimport os\nimport tempfile\nimport time\nimport traceback\n\nfrom avocado.core import nrunner\nfrom avocado.core.runners.utils import messages\nfrom avocado.core.test import TestID\nfrom avocado.core.tree import TreeNodeEnvOnly\nfrom avocado.core.utils import loader\nfrom avocado.core.varianter import is_empty_variant\n\n\nclass AvocadoInstrumentedTestRunner(nrunner.BaseRunner):\n    \"\"\"\n    Runner for Avocado INSTRUMENTED tests\n\n    Runnable attributes usage:\n\n     * uri: path to a test file, combined with an Avocado.Test\n       inherited class name and method.  The test file path and\n       class and method names should be separated by a \":\".  One\n       example of a valid uri is \"mytest.py:Class.test_method\".\n\n     * args: not used\n    \"\"\"\n    DEFAULT_TIMEOUT = 86400\n\n    @staticmethod\n    def _create_params(runnable):\n        \"\"\"Create params for the test\"\"\"\n        if runnable.variant is None:\n            return None\n\n        # rebuild the variant tree\n        variant_tree_nodes = [TreeNodeEnvOnly(path, env) for path, env\n                              in runnable.variant['variant']]\n\n        if not is_empty_variant(variant_tree_nodes):\n            tree_nodes = variant_tree_nodes\n            paths = runnable.variant['paths']\n            return tree_nodes, paths\n\n    @staticmethod\n    def _run_avocado(runnable, queue):\n        try:\n            # This assumes that a proper resolution (see resolver module)\n            # was performed, and that a URI contains:\n            # 1) path to python module\n            # 2) class\n            # 3) method\n            #\n            # To be defined: if the resolution uri should be composed like\n            # this, or broken down and stored into other data fields\n            module_path, klass_method = runnable.uri.split(':', 1)\n\n            klass, method = klass_method.split('.', 1)\n\n            params = AvocadoInstrumentedTestRunner._create_params(runnable)\n            result_dir = (runnable.output_dir or\n                          tempfile.mkdtemp(prefix=\".avocado-task\"))\n            test_factory = [klass,\n                            {'name': TestID(1, runnable.uri),\n                             'methodName': method,\n                             'config': runnable.config,\n                             'modulePath': module_path,\n                             'params': params,\n                             'tags': runnable.tags,\n                             'run.results_dir': result_dir,\n                             }]\n\n            messages.start_logging(runnable.config, queue)\n\n            if 'COVERAGE_RUN' in os.environ:\n                from coverage import Coverage\n                coverage = Coverage()\n                coverage.start()\n\n            instance = loader.load_test(test_factory)\n            early_state = instance.get_state()\n            early_state['type'] = \"early_state\"\n            queue.put(early_state)\n            instance.run_avocado()\n\n            if 'COVERAGE_RUN' in os.environ:\n                coverage.stop()\n                coverage.save()\n\n            state = instance.get_state()\n            fail_reason = state.get('fail_reason')\n            queue.put(messages.WhiteboardMessage.get(state['whiteboard']))\n            queue.put(messages.FinishedMessage.get(state['status'].lower(),\n                                                   fail_reason=fail_reason))\n        except Exception as e:\n            queue.put(messages.StderrMessage.get(traceback.format_exc()))\n            queue.put(messages.FinishedMessage.get('error', fail_reason=str(e)))\n\n    def run(self):\n        yield messages.StartedMessage.get()\n        try:\n            queue = multiprocessing.SimpleQueue()\n            process = multiprocessing.Process(target=self._run_avocado,\n                                              args=(self.runnable, queue))\n\n            process.start()\n\n            time_started = time.monotonic()\n\n            timeout = float(self.DEFAULT_TIMEOUT)\n            most_current_execution_state_time = None\n            while True:\n                time.sleep(nrunner.RUNNER_RUN_CHECK_INTERVAL)\n                now = time.monotonic()\n                if queue.empty():\n                    if most_current_execution_state_time is not None:\n                        next_execution_state_mark = (most_current_execution_state_time +\n                                                     nrunner.RUNNER_RUN_STATUS_INTERVAL)\n                    if (most_current_execution_state_time is None or\n                            now > next_execution_state_mark):\n                        most_current_execution_state_time = now\n                        yield messages.RunningMessage.get()\n                    if (now - time_started) > timeout:\n                        process.terminate()\n                        yield messages.FinishedMessage.get('interrupted',\n                                                           'timeout')\n                        break\n                else:\n                    message = queue.get()\n                    if message.get('type') == 'early_state':\n                        timeout = float(message.get('timeout') or\n                                        self.DEFAULT_TIMEOUT)\n                    else:\n                        yield message\n                    if message.get('status') == 'finished':\n                        break\n        except Exception as e:\n            yield messages.StderrMessage.get(traceback.format_exc())\n            yield messages.FinishedMessage.get('error', fail_reason=str(e))\n\n\nclass RunnerApp(nrunner.BaseRunnerApp):\n    PROG_NAME = 'avocado-runner-avocado-instrumented'\n    PROG_DESCRIPTION = 'nrunner application for avocado-instrumented tests'\n    RUNNABLE_KINDS_CAPABLE = {\n        'avocado-instrumented': AvocadoInstrumentedTestRunner\n    }\n\n\ndef main():\n    nrunner.main(RunnerApp)\n\n\nif __name__ == '__main__':\n    main()\n", "path": "avocado/core/runners/avocado_instrumented.py"}]}