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

# -*- 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')