You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
92 lines
3.4 KiB
92 lines
3.4 KiB
# -*- coding: utf-8 -*-
|
|
# t10-verify.py — 票 10 验收:源码接口钥匙 ↔ Bruno 集合 docs 首行钥匙 双零差集
|
|
# 钥匙 = METHOD + 完整路径(两侧均按 (METHOD, path) 去重比对;tag 多副本在集合侧归一)
|
|
import io, os, re, sys
|
|
|
|
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')
|
|
ROOT = r'D:\code\crm-backend-matt'
|
|
DOCS = r'D:\code\crm-api-docs'
|
|
SRC_ROOTS = ['crm-auth/src/main/java', 'crm-file/src/main/java', 'crm-lead/src/main/java',
|
|
'crm-opportunity/src/main/java', 'crm-rule/src/main/java',
|
|
'crm-preference/src/main/java', 'crm-dict/src/main/java']
|
|
|
|
def norm(p):
|
|
if not p:
|
|
return ''
|
|
p = '/' + p.lstrip('/')
|
|
while '//' in p:
|
|
p = p.replace('//', '/')
|
|
return p.rstrip('/') or '/'
|
|
|
|
# ---- 源码钥匙 ----
|
|
rx_ctrl = re.compile(r'@(?:Rest)?Controller\b')
|
|
rx_cls = re.compile(r'@RequestMapping\(\s*(?:value\s*=\s*)?"([^"]+)"')
|
|
rx_map = re.compile(r'@(Get|Post|Put|Delete)Mapping\(\s*(?:value\s*=\s*)?"?([^")\s]*)"?')
|
|
rx_map0 = re.compile(r'@(Get|Post|Put|Delete)Mapping\b(?!\()')
|
|
src = {}
|
|
|
|
def add_key(method, path):
|
|
src.setdefault((method.upper(), norm(path)), []).append(rel)
|
|
|
|
for r in SRC_ROOTS:
|
|
base = os.path.join(ROOT, r)
|
|
for root, dirs, files in os.walk(base):
|
|
for fn in files:
|
|
if not fn.endswith('.java'):
|
|
continue
|
|
p = os.path.join(root, fn)
|
|
rel = os.path.relpath(p, ROOT)
|
|
txt = open(p, 'r', encoding='utf-8', errors='replace').read()
|
|
if not rx_ctrl.search(txt):
|
|
continue
|
|
mcls = rx_cls.search(txt)
|
|
basep = mcls.group(1) if mcls else ''
|
|
for m in rx_map.finditer(txt):
|
|
add_key(m.group(1), basep + m.group(2))
|
|
for m in rx_map0.finditer(txt):
|
|
add_key(m.group(1), basep)
|
|
|
|
# ---- 集合钥匙 ----
|
|
rx_doc = re.compile(r'docs\s*\{[^`]*?`([^`]+)`', re.S)
|
|
doc = {}
|
|
bad = []
|
|
for root, dirs, files in os.walk(DOCS):
|
|
if 'environments' in root:
|
|
continue
|
|
for fn in files:
|
|
if not fn.endswith('.bru') or fn == 'collection.bru':
|
|
continue
|
|
p = os.path.join(root, fn)
|
|
txt = open(p, 'r', encoding='utf-8-sig', errors='replace').read()
|
|
if 'generated' not in txt[:400]:
|
|
continue
|
|
m = rx_doc.search(txt)
|
|
if not m:
|
|
bad.append(('NO-KEY', os.path.relpath(p, DOCS)))
|
|
continue
|
|
parts = m.group(1).strip().split(None, 1)
|
|
if len(parts) != 2:
|
|
bad.append(('BAD-KEY', os.path.relpath(p, DOCS) + ' :: ' + m.group(1)))
|
|
continue
|
|
rel = os.path.relpath(p, DOCS)
|
|
doc.setdefault((parts[0].upper(), norm(parts[1])), []).append(rel)
|
|
|
|
# ---- 比对 ----
|
|
missing = sorted(set(src) - set(doc))
|
|
extra = sorted(set(doc) - set(src))
|
|
print('source keys: %d collection keys: %d' % (len(src), len(doc)))
|
|
print('')
|
|
if missing:
|
|
print('---- MISSING(源码有、集合无)%d ----' % len(missing))
|
|
for k in missing:
|
|
print(' %-6s %-58s %s' % (k[0], k[1], src[k][0]))
|
|
if extra:
|
|
print('---- EXTRA(集合有、源码无)%d ----' % len(extra))
|
|
for k in extra:
|
|
print(' %-6s %-58s %s' % (k[0], k[1], doc[k][0]))
|
|
if bad:
|
|
print('---- UNRECOGNIZED %d ----' % len(bad))
|
|
for b in bad:
|
|
print(' %s %s' % b)
|
|
print('')
|
|
print('RESULT:', 'PASS 双零差集' if not missing and not extra and not bad else 'FAIL')
|
|
|