pytorch/tools/stats/import_test_stats.py
Jane Xu b96acb7591 Allow disabled tests to be re-enabled with IGNORE_DISABLED_ISSUES (#62686)
Summary:
Part 1 of fixing https://github.com/pytorch/pytorch/issues/62359

Pull Request resolved: https://github.com/pytorch/pytorch/pull/62686

Test Plan:
1. Check out this PR and run `python setup.py install`.
2. The test we will be running requires CUDA. If you don't have CUDA, you can try this on another device or simply comment out the skipIf statement before the `test_jit_cuda_extension` test in `test_cpp_extensions_jit.py`
3. Run: `IN_CI=1 python test/run_test.py -i test_cpp_extensions_jit -- -k test_jit_cuda_extension` and notice that it should skip. If it doesn't skip, edit test/.pytorch-disabled-tests.json: modify the platforms list of the first issue (61655) to include whatever platform you are on (macos or linux), and just run `python test/test_cpp_extensions_jit.py -v -k test_jit_cuda_extension --import-disabled-tests` to make sure it skips.
4. Now `export PYTORCH_IGNORE_DISABLED_ISSUES=61655` or `export PYTORCH_IGNORE_DISABLED_ISSUES=34952,61655`.
5. `rm test/.pytorch-*` to clear the cached files.
6. Run the same command as in step 5 and note that it SHOULDN'T skip. It should run.

Reviewed By: walterddr, samestep

Differential Revision: D30108773

Pulled By: janeyx99

fbshipit-source-id: dbf015a266f57577dc9283b0cdff720083b5c0cb
2021-08-05 09:05:40 -07:00

99 lines
4.2 KiB
Python

#!/usr/bin/env python3
import datetime
import json
import os
import pathlib
import re
from typing import Any, Callable, Dict, List, Optional, cast
from urllib.request import urlopen
# PYTORCH_IGNORE_DISABLED_ISSUES should only be set during CI (along with IN_CI) as a
# comma-separated list of issue numbers. The intent is to re-enable any disabled tests
# associated with the issues in this list.
#
# There is normally no reason to use this locally as the disabled tests list should not
# affect your local development and every test should be enabled. If for whatever reason
# you would like to use this during local development, please note the following caveat:
#
# Whenever you set OR reset PYTORCH_IGNORE_DISABLED_ISSUES, you should delete the existing
# .pytorch-disabled-tests.json and redownload/parse the file for your change to apply, as
# PYTORCH_IGNORE_DISABLED_ISSUES is used during the parsing stage. To download the files,
# run test/run_test.py with IN_CI=1.
IGNORE_DISABLED_ISSUES: List[str] = os.getenv('PYTORCH_IGNORE_DISABLED_ISSUES', '').split(',')
SLOW_TESTS_FILE = '.pytorch-slow-tests.json'
DISABLED_TESTS_FILE = '.pytorch-disabled-tests.json'
FILE_CACHE_LIFESPAN_SECONDS = datetime.timedelta(hours=3).seconds
def fetch_and_cache(
dirpath: str,
name: str,
url: str,
process_fn: Callable[[Dict[str, Any]], Dict[str, Any]]
) -> Dict[str, Any]:
"""
This fetch and cache utils allows sharing between different process.
"""
path = os.path.join(dirpath, name)
def is_cached_file_valid() -> bool:
# Check if the file is new enough (see: FILE_CACHE_LIFESPAN_SECONDS). A real check
# could make a HEAD request and check/store the file's ETag
fname = pathlib.Path(path)
now = datetime.datetime.now()
mtime = datetime.datetime.fromtimestamp(fname.stat().st_mtime)
diff = now - mtime
return diff.total_seconds() < FILE_CACHE_LIFESPAN_SECONDS
if os.path.exists(path) and is_cached_file_valid():
# Another test process already downloaded the file, so don't re-do it
with open(path, "r") as f:
return cast(Dict[str, Any], json.load(f))
try:
contents = urlopen(url, timeout=1).read().decode('utf-8')
processed_contents = process_fn(json.loads(contents))
with open(path, "w") as f:
f.write(json.dumps(processed_contents))
return processed_contents
except Exception as e:
print(f'Could not download {url} because of error {e}.')
return {}
def get_slow_tests(dirpath: str, filename: str = SLOW_TESTS_FILE) -> Optional[Dict[str, float]]:
url = "https://raw.githubusercontent.com/pytorch/test-infra/main/stats/slow-tests.json"
try:
return fetch_and_cache(dirpath, filename, url, lambda x: x)
except Exception:
print("Couldn't download slow test set, leaving all tests enabled...")
return {}
def get_disabled_tests(dirpath: str, filename: str = DISABLED_TESTS_FILE) -> Optional[Dict[str, Any]]:
def process_disabled_test(the_response: Dict[str, Any]) -> Dict[str, Any]:
disabled_test_from_issues = dict()
for item in the_response['items']:
title = item['title']
key = 'DISABLED '
issue_url = item['html_url']
issue_number = issue_url.split('/')[-1]
if title.startswith(key) and issue_number not in IGNORE_DISABLED_ISSUES:
test_name = title[len(key):].strip()
body = item['body']
platforms_to_skip = []
key = 'platforms:'
for line in body.splitlines():
line = line.lower()
if line.startswith(key):
pattern = re.compile(r"^\s+|\s*,\s*|\s+$")
platforms_to_skip.extend([x for x in pattern.split(line[len(key):]) if x])
disabled_test_from_issues[test_name] = (item['html_url'], platforms_to_skip)
return disabled_test_from_issues
try:
url = 'https://raw.githubusercontent.com/pytorch/test-infra/main/stats/disabled-tests.json'
return fetch_and_cache(dirpath, filename, url, process_disabled_test)
except Exception:
print("Couldn't download test skip set, leaving all tests enabled...")
return {}