|
6 | 6 | import sys |
7 | 7 | rows = [l.rstrip('\n').split('\t') for l in open(sys.argv[1]) if l.strip()] |
8 | 8 | tool = None |
9 | | -roots, nodes, files, direct = {}, {}, {}, {} |
| 9 | +roots, root_projects, nodes, files, direct, edges = {}, {}, {}, {}, {}, {} |
10 | 10 | for r in rows: |
11 | 11 | if r[0] == 'meta': tool = r[1] |
12 | | - elif r[0] == 'root': roots[r[1]] = (r[4] == '1') # rootId -> prod |
| 12 | + elif r[0] == 'root': |
| 13 | + # rootId to prod and to projectKey. |
| 14 | + roots[r[1]] = (r[4] == '1') |
| 15 | + root_projects[r[1]] = r[2] |
13 | 16 | elif r[0] == 'node': |
14 | 17 | nodes.setdefault(r[2], set()).add(r[1]) # coordId -> {rootId} |
15 | 18 | if r[8] == '1': direct.setdefault(r[2], set()).add(r[1]) # coordId -> {rootId where direct} |
16 | 19 | elif r[0] == 'file': files.setdefault(r[2], set()).add(r[3]) # coordId -> {path} |
| 20 | + elif r[0] == 'edge': |
| 21 | + # (parent, child) to the roots that hold the edge. |
| 22 | + edges.setdefault((r[2], r[3]), set()).add(r[1]) |
17 | 23 |
|
18 | 24 | errors = [] |
19 | 25 |
|
@@ -61,15 +67,48 @@ def has_jar(cid): return any(p.endswith('.jar') for p in files.get(cid, ())) |
61 | 67 | elif not in_prod(lib): errors.append("internal module demo:lib not in app's prod root") |
62 | 68 | elif not direct.get(lib): errors.append("internal module demo:lib not marked direct") |
63 | 69 |
|
64 | | -# Scope conflict: Maven keeps demo.ext:shared under the test parent while its effective |
65 | | -# scope is compile, so it must land in the dev root. Reachability (checked by |
66 | | -# ../assert-reachability.py) additionally proves it kept its parent edge. |
67 | | -shared = coord('demo.ext:shared:jar:') |
68 | | -if not shared: errors.append("missing scope-conflict dep demo.ext:shared") |
69 | | -elif in_prod(shared): errors.append("scope-conflict demo.ext:shared wrongly in a prod root") |
| 70 | +def edge_roots(parent, child): |
| 71 | + return edges.get((parent, child), set()) |
| 72 | + |
| 73 | +def edge_pair(parent, child): |
| 74 | + """Both coordinates, or None after reporting the missing ones.""" |
| 75 | + found = (coord(parent), coord(child)) |
| 76 | + missing = [p for p, c in zip((parent, child), found) if not c] |
| 77 | + if missing: |
| 78 | + errors.append(f"missing {', '.join(m.rstrip(':') for m in missing)}") |
| 79 | + return None |
| 80 | + return found |
| 81 | + |
| 82 | +# Scope conflict: Maven keeps demo.ext:shared under the test parent but selects compile, the |
| 83 | +# scope conflict-prod's path gives it, so it is on the runtime classpath. Its edge from |
| 84 | +# conflict-prod, onto the copy Maven kept under the test parent, keeps it reachable in the prod root. |
| 85 | +pair = edge_pair('demo.ext:conflict-prod:jar:', 'demo.ext:shared:jar:') |
| 86 | +if pair: |
| 87 | + if not in_prod(pair[1]): errors.append("scope-conflict demo.ext:shared not in a prod root") |
| 88 | + elif not any(roots.get(rid) for rid in edge_roots(*pair)): |
| 89 | + errors.append("edge demo.ext:conflict-prod -> demo.ext:shared missing from a prod root") |
| 90 | + |
| 91 | +# An edge onto a dependency Maven kept elsewhere: dup-io's dup-util is the direct one. |
| 92 | +pair = edge_pair('demo.ext:dup-io:jar:', 'demo.ext:dup-util:jar:') |
| 93 | +if pair and not edge_roots(*pair): errors.append("edge demo.ext:dup-io -> demo.ext:dup-util missing") |
| 94 | + |
| 95 | +# A mediated edge: med-io asks for another med-util than mid declares, and points at mid's. |
| 96 | +# coord() fails if the med-util version med-io asked for is also emitted. |
| 97 | +pair = edge_pair('demo.ext:med-io:jar:', 'demo.ext:med-util:jar:') |
| 98 | +if pair and not any(root_projects.get(rid) == 'demo:mid:1.0' for rid in edge_roots(*pair)): |
| 99 | + errors.append("edge demo.ext:med-io -> demo.ext:med-util missing from mid") |
| 100 | + |
| 101 | +# An edge across the prod/dev split: container-lib (compile) onto container-api, which app |
| 102 | +# declares provided. The edge is kept and container-api stays dev. |
| 103 | +pair = edge_pair('demo.ext:container-lib:jar:', 'demo.ext:container-api:jar:') |
| 104 | +if pair: |
| 105 | + if in_prod(pair[1]): errors.append("provided demo.ext:container-api wrongly in a prod root") |
| 106 | + elif not in_prod(pair[0]): errors.append("demo.ext:container-lib not in a prod root") |
| 107 | + elif not edge_roots(*pair): |
| 108 | + errors.append("edge demo.ext:container-lib -> demo.ext:container-api missing") |
70 | 109 |
|
71 | 110 | if errors: |
72 | 111 | print("FAIL:") |
73 | 112 | for e in errors: print(" -", e) |
74 | 113 | sys.exit(1) |
75 | | -print(f"PASS: tool=maven; {ext} prod+jar; harness/harness-core dev; internal demo:lib (bare id, direct); {shared} dev") |
| 114 | +print(f"PASS: tool=maven; {ext} prod+jar; harness/harness-core dev; internal demo:lib (bare id, direct); demo.ext:shared prod; edges onto kept dependencies") |
0 commit comments