| 840 | |
| 841 | |
| 842 | class TraceReportGenerator(object): |
| 843 | |
| 844 | def __init__(self, out_file_path): |
| 845 | self._filename = out_file_path |
| 846 | self._file = open(out_file_path, 'w') |
| 847 | self._wreckage_filename = out_file_path + '.wreckage' |
| 848 | self._test_messages = {} |
| 849 | self._test_duration = {} |
| 850 | # Some machinery to avoid data corruption due sloppy fork() |
| 851 | self._current_test = (None, None) |
| 852 | self._pid = os.getpid() |
| 853 | self._check_intricate_respawn() |
| 854 | |
| 855 | def _check_intricate_respawn(self): |
| 856 | pid_file = self._filename + '.pid' |
| 857 | try: |
| 858 | # python2 doesn't support open(f, 'x') |
| 859 | afile = os.fdopen(os.open(pid_file, os.O_WRONLY | os.O_EXCL | os.O_CREAT), 'w') |
| 860 | afile.write(str(self._pid)) |
| 861 | afile.close() |
| 862 | return |
| 863 | except OSError as e: |
| 864 | if e.errno != errno.EEXIST: |
| 865 | raise |
| 866 | |
| 867 | # Looks like the test binary was respawned |
| 868 | if from_ya_test(): |
| 869 | try: |
| 870 | with open(pid_file) as afile: |
| 871 | prev_pid = afile.read() |
| 872 | except Exception as e: |
| 873 | prev_pid = '(failed to obtain previous pid: {})'.format(e) |
| 874 | |
| 875 | parts = [ |
| 876 | "Aborting test run: test machinery found that the test binary {} has already been run before.".format(sys.executable), |
| 877 | "Looks like test has incorrect respawn/relaunch logic within test binary.", |
| 878 | "Test should not try to restart itself - this is a poorly designed test case that leads to errors and could corrupt internal test machinery files.", |
| 879 | "Debug info: previous pid:{} current:{}".format(prev_pid, self._pid), |
| 880 | ] |
| 881 | msg = '\n'.join(parts) |
| 882 | yatest_logger.error(msg) |
| 883 | |
| 884 | if filelock: |
| 885 | lock = filelock.FileLock(self._wreckage_filename + '.lock') |
| 886 | lock.acquire() |
| 887 | |
| 888 | with open(self._wreckage_filename, 'a') as afile: |
| 889 | self._file = afile |
| 890 | |
| 891 | self._dump_trace('chunk_event', {"errors": [('fail', '[[bad]]' + msg)]}) |
| 892 | |
| 893 | raise Exception(msg) |
| 894 | else: |
| 895 | # Test binary is launched without `ya make -t`'s testing machinery - don't rely on clean environment |
| 896 | pass |
| 897 | |
| 898 | def on_start_test_class(self, test_item): |
| 899 | pytest_config.ya.set_test_item_node_id(test_item.nodeid) |