forked from rurema/bitclust
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmd-bridge-check.rb
More file actions
executable file
·94 lines (86 loc) · 3.29 KB
/
Copy pathmd-bridge-check.rb
File metadata and controls
executable file
·94 lines (86 loc) · 3.29 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
#!/usr/bin/env ruby
# frozen_string_literal: true
#
# md ブリッジのパーサレベル等価検証。
# 各ライブラリを「旧ソース(doctree の .rd)」と「md ツリー → MarkdownBridge で
# 生成した rd ツリー」の両方から RRDParser でパースし、クラス・エントリ構造が
# 一致することを確認する。
#
# usage: ruby tools/md-bridge-check.rb <doctree-src-root> <md-tree-root> [--version V] [-v]
$LOAD_PATH.unshift File.expand_path('../lib', __dir__)
require 'tmpdir'
require 'bitclust'
require 'bitclust/markdown_bridge'
version = '3.4'
verbose = false
paths = []
args = ARGV.dup
until args.empty?
case (a = args.shift)
when '--version' then version = args.shift
when '-v' then verbose = true
else paths << a
end
end
src_root, md_root = paths
abort "usage: #{$0} <doctree-src-root> <md-tree-root> [--version V]" unless src_root && md_root
params = { 'version' => version }
def library_names(root, params)
# 旧 LIBRARIES には重複エントリがある(webrick/httputils)ため uniq
BitClust::Preprocessor.read(File.join(root, 'LIBRARIES'), params)
.lines.map(&:strip).reject(&:empty?).uniq
end
# ライブラリを単体パースし、{[type, class名] => 整列済みエントリ名} を返す
def structure(root, lib, params)
db = BitClust::MethodDatabase.dummy(params)
library = BitClust::RRDParser.new(db).parse_file(File.join(root, "#{lib}.rd"), lib, params)
library.classes.to_h do |c|
[[c.type.to_s, c.name], c.entries.flat_map(&:names).sort]
end
rescue StandardError => e
{ error: "#{e.class}: #{e.message}" }
end
Dir.mktmpdir do |bridge|
t0 = Time.now
BitClust::MarkdownBridge.build(md_root, bridge)
puts "bridge built in #{(Time.now - t0).round(1)}s"
old_libs = library_names(src_root, params)
new_libs = library_names(bridge, params)
puts "library set @#{params['version']}: " \
"#{old_libs.sort == new_libs.sort ? 'OK' : 'MISMATCH'} " \
"(old #{old_libs.size}, new #{new_libs.size})"
(old_libs - new_libs).each { |l| puts " missing in bridge: #{l}" }
(new_libs - old_libs).each { |l| puts " extra in bridge: #{l}" }
ok = 0
diffs = []
errors = []
(old_libs & new_libs).sort.each do |lib|
old_s = structure(src_root, lib, params)
new_s = structure(bridge, lib, params)
if old_s[:error] || new_s[:error]
if old_s[:error].to_s == new_s[:error].to_s
ok += 1 # 両側同一条件で失敗(dummy DB 都合等)は等価とみなす
else
errors << [lib, old_s[:error], new_s[:error]]
end
next
end
if old_s == new_s
ok += 1
puts "OK #{lib}" if verbose
else
diffs << lib
puts "DIFF #{lib}"
(old_s.keys - new_s.keys).each { |k| puts " only in old: #{k.inspect}" }
(new_s.keys - old_s.keys).each { |k| puts " only in new: #{k.inspect}" }
(old_s.keys & new_s.keys).each do |k|
next if old_s[k] == new_s[k]
puts " #{k.inspect}: entries differ"
puts " only old: #{(old_s[k] - new_s[k]).first(5).inspect}"
puts " only new: #{(new_s[k] - old_s[k]).first(5).inspect}"
end
end
end
puts "#{ok}/#{(old_libs & new_libs).size} libraries structurally identical"
errors.each { |lib, o, n| puts " ERROR #{lib}: old=#{o.inspect} new=#{n.inspect}" }
end