1# Copyright (c) 2007, The RubyCocoa Project. 2# All Rights Reserved. 3# 4# RubyCocoa is free software, covered under either the Ruby's license or the 5# LGPL. See the COPYRIGHT file for more information. 6 7# A BridgeSupport files verifier, based on the generated Ruby files from 8# gen_bridge_doc. 9# 10# To run it from the source root: 11# ruby framework/tool/verify_bridge_metadata.rb framework/bridge-support 12# framework/bridge-doc 13# 14# (Make sure to have run install.rb config and doc tasks before.) 15 16begin require 'rubygems'; rescue LoadError; end 17require 'xml/libxml' 18 19def die(s) 20 $stderr.puts s 21 exit 1 22end 23 24def log(s) 25 $stderr.puts s if $VERBOSE 26end 27 28def lputs(p, s) 29 puts p.ljust(50) + s 30end 31 32# Check arguments. 33if ARGV.size != 2 34 die "Usage: #{__FILE__} <bridge-support-dir> <bridge-doc-dir>" 35end 36bs_dir, doc_dir = ARGV 37$doc_ruby_dir = doc_ruby_dir = File.join(doc_dir, 'ruby') 38 39# Setup some autoload magic first. 40module OSX 41 def self.const_missing(sym) 42 return Object if sym == :ObjcID 43 path = "#{$doc_ruby_dir}/#{sym}.rb" 44 if File.exist?(path) 45 require(path) 46 if const_defined?(sym) 47 const_get(sym) 48 end 49 end 50 end 51end 52 53# Load bridge support and Ruby files. 54class BSDocs 55 def initialize(bs_dir) 56 @bs_docs = Dir.glob(bs_dir + '/*.bridgesupport').map { |f| XML::Document.file(f) } 57 end 58 def any?(xpath) 59 xpath = '/signatures/' + xpath 60 @bs_docs.each do |doc| 61 set = doc.find(xpath) 62 return set[0] unless set.empty? 63 end 64 return nil 65 end 66end 67bs_docs = BSDocs.new(bs_dir) 68Dir.glob(doc_ruby_dir + '/*.rb').map { |x| require(x) } 69 70class BSTest 71 attr_accessor :name, :failures, :count 72 def self.go(name) 73 test = self.new 74 test.name = name 75 test.failures = [] 76 test.count = 0 77 @tests ||= [] 78 @tests << test 79 yield(test) 80 end 81 def self.all_tests 82 @tests 83 end 84 def success(msg) 85 log(msg) 86 @count += 1 87 end 88 def failure(msg) 89 log(msg) 90 @failures << msg 91 @count += 1 92 end 93end 94 95log 'Verifying functions...' 96BSTest.go('Functions') do |test| 97 OSX.methods(false).each do |func_name| 98 if elem = bs_docs.any?("function[@name=\"#{func_name}\"]") 99 argc = elem.find('arg').length 100 e_argc = OSX.method(func_name).arity 101 if e_argc < 0 and elem['variadic'] == 'true' 102 e_argc = e_argc.abs - 1 103 end 104 if e_argc == argc 105 test.success func_name 106 else 107 test.failure "#{func_name} has wrong arity (expected #{e_argc}, got #{argc})" 108 end 109 else 110 test.failure "#{func_name} is missing" 111 end 112 end 113end 114 115log 'Verifying constants...' 116BSTest.go('Constants') do |test| 117 OSX.constants.each do |const_name| 118 o = OSX.const_get(const_name) 119 next unless o.nil? # Constants are nil 120 low_const_name = const_name.sub(/^[A-Z]/) { |s| s.downcase } 121 if bs_docs.any?("constant[@name=\"#{const_name}\" or @name=\"#{low_const_name}\"]") \ 122 or bs_docs.any?("enum[@name=\"#{const_name}\" or @name=\"#{low_const_name}\"]") 123 124 test.success const_name 125 else 126 test.failure "#{const_name} is missing" 127 end 128 end 129end 130 131# Print test results 132BSTest.all_tests.each do |test| 133 puts "#{test.name}: #{test.count} test(s), #{test.failures.length} failure(s)" 134 test.failures.each { |s| puts "-> " + s } 135end 136