import subprocess
import sys
import tempfile
+from typing import List, Optional, Tuple
+import xml.etree.ElementTree as ET
import pytest
sys.path.append(os.path.dirname(__file__))
-from gvtest import run_c #pylint: disable=C0413
+from gvtest import ROOT, run_c #pylint: disable=C0413
# The terminology used in rtest.py is a little inconsistent. At the
# end it reports the total number of tests, the number of "failures"
'{P : [0.000000,0.000000,0.000000,36.000000,54.000000,' \
'36.000000,54.000000,0.000000]}\n' \
']\n'
+
+# find all .vcxproj files
+VCXPROJS: List[Path] = []
+for root, _, files in os.walk(ROOT):
+ for stem in files:
+ # skip files generated by MSBuild itself
+ if stem in ("VCTargetsPath.vcxproj", "CompilerIdC.vcxproj",
+ "CompilerIdCXX.vcxproj"):
+ continue
+ p = Path(root) / stem
+ if p.suffix != ".vcxproj":
+ continue
+ VCXPROJS.append(p)
+
+@pytest.mark.parametrize("vcxproj", VCXPROJS)
+def test_vcxproj_inclusive(vcxproj: Path):
+ """check .vcxproj files correspond to .vcxproj.filters files"""
+
+ def fix_sep(path: str) -> str:
+ """translate Windows path separators to ease running this on non-Windows"""
+ return path.replace("\\", os.sep)
+
+ # FIXME: files missing a filters file
+ FILTERS_WAIVERS = (Path("lib/version/version.vcxproj"),)
+
+ filters = Path(f"{str(vcxproj)}.filters")
+ if vcxproj.relative_to(ROOT) not in FILTERS_WAIVERS:
+ assert filters.exists(), \
+ f"no {str(filters)} corresponding to {str(vcxproj)}"
+
+ # namespace the MSBuild elements live in
+ ns = "http://schemas.microsoft.com/developer/msbuild/2003"
+
+ # parse XML out of the .vcxproj file
+ srcs1 = set()
+ tree = ET.parse(vcxproj)
+ root = tree.getroot()
+ for elem in root:
+ if elem.tag == f"{{{ns}}}ItemGroup":
+ for child in elem:
+ if child.tag in (f"{{{ns}}}ClInclude", f"{{{ns}}}ClCompile"):
+ filename = fix_sep(child.attrib["Include"])
+ assert filename not in srcs1, \
+ f"duplicate source {filename} in {str(vcxproj)}"
+ srcs1.add(filename)
+
+ # parse XML out of the .vcxproj.filters file
+ if filters.exists():
+ srcs2 = set()
+ tree = ET.parse(filters)
+ root = tree.getroot()
+ for elem in root:
+ if elem.tag == f"{{{ns}}}ItemGroup":
+ for child in elem:
+ if child.tag in (f"{{{ns}}}ClInclude", f"{{{ns}}}ClCompile"):
+ filename = fix_sep(child.attrib["Include"])
+ assert filename not in srcs2, \
+ f"duplicate source {filename} in {str(filters)}"
+ srcs2.add(filename)
+
+ assert srcs1 == srcs2, \
+ "mismatch between sources in {str(vcxproj)} and {str(filters)}"