Skip to content
Fetching contributors…
Cannot retrieve contributors at this time
305 lines (263 sloc) 10.7 KB
require File.join(File.dirname(__FILE__), "spec_helper")
include CodeObjects
require "thread"
describe YARD::Registry do
before { Registry.clear }
describe '.yardoc_file_for_gem' do
before do
@gem = mock('gem')
@gem.stub!(:name).and_return('foo')
@gem.stub!(:full_name).and_return('foo-1.0')
@gem.stub!(:full_gem_path).and_return('/path/to/foo')
end
it "should return nil if gem isn't found" do
Gem.source_index.should_receive(:find_name).with('foo', '>= 0').and_return([])
Registry.yardoc_file_for_gem('foo').should == nil
end
it "should allow version to be specified" do
Gem.source_index.should_receive(:find_name).with('foo', '= 2').and_return([])
Registry.yardoc_file_for_gem('foo', '= 2').should == nil
end
it "should return existing .yardoc path for gem when for_writing=false" do
File.should_receive(:exist?).and_return(false)
File.should_receive(:exist?).with('/path/to/foo/.yardoc').and_return(true)
Gem.source_index.should_receive(:find_name).with('foo', '>= 0').and_return([@gem])
Registry.yardoc_file_for_gem('foo').should == '/path/to/foo/.yardoc'
end
it "should return nil if no .yardoc path exists in gem when for_writing=false" do
File.should_receive(:exist?).and_return(false)
File.should_receive(:exist?).with('/path/to/foo/.yardoc').and_return(false)
Gem.source_index.should_receive(:find_name).with('foo', '>= 0').and_return([@gem])
Registry.yardoc_file_for_gem('foo').should == nil
end
it "should search local gem path first if for_writing=false" do
File.should_receive(:exist?).and_return(true)
Gem.source_index.should_receive(:find_name).with('foo', '>= 0').and_return([@gem])
Registry.yardoc_file_for_gem('foo').should =~ %r{/.yard/gem_index/foo-1.0.yardoc$}
end
it "should return global .yardoc path for gem if for_writing=true and dir is writable" do
File.should_receive(:writable?).with(@gem.full_gem_path).and_return(true)
Gem.source_index.should_receive(:find_name).with('foo', '>= 0').and_return([@gem])
Registry.yardoc_file_for_gem('foo', '>= 0', true).should == '/path/to/foo/.yardoc'
end
it "should return local .yardoc path for gem if for_writing=true and dir is not writable" do
File.should_receive(:writable?).with(@gem.full_gem_path).and_return(false)
Gem.source_index.should_receive(:find_name).with('foo', '>= 0').and_return([@gem])
Registry.yardoc_file_for_gem('foo', '>= 0', true).should =~ %r{/.yard/gem_index/foo-1.0.yardoc$}
end
it "should return gem path if gem starts with yard-doc- and for_writing=false" do
@gem.stub!(:name).and_return('yard-doc-core')
@gem.stub!(:full_name).and_return('yard-doc-core-1.0')
@gem.stub!(:full_gem_path).and_return('/path/to/yard-doc-core')
Gem.source_index.should_receive(:find_name).with('yard-doc-core', '>= 0').and_return([@gem])
File.should_receive(:exist?).with('/path/to/yard-doc-core/.yardoc').and_return(true)
Registry.yardoc_file_for_gem('yard-doc-core').should == '/path/to/yard-doc-core/.yardoc'
end
it "should return nil if gem starts with yard-doc- and for_writing=true" do
@gem.stub!(:name).and_return('yard-doc-core')
@gem.stub!(:full_name).and_return('yard-doc-core-1.0')
@gem.stub!(:full_gem_path).and_return('/path/to/yard-doc-core')
Gem.source_index.should_receive(:find_name).with('yard-doc-core', '>= 0').and_return([@gem])
File.should_receive(:exist?).with('/path/to/yard-doc-core/.yardoc').and_return(true)
Registry.yardoc_file_for_gem('yard-doc-core', '>= 0', true).should == nil
end
end
describe '.root' do
it "should have an empty path for root" do
Registry.root.path.should == ""
end
end
describe '.resolve' do
it "should resolve any existing namespace" do
o1 = ModuleObject.new(:root, :A)
o2 = ModuleObject.new(o1, :B)
o3 = ModuleObject.new(o2, :C)
Registry.resolve(o1, "B::C").should == o3
Registry.resolve(:root, "A::B::C")
end
it "should resolve an object in the root namespace when prefixed with ::" do
o1 = ModuleObject.new(:root, :A)
o2 = ModuleObject.new(o1, :B)
o3 = ModuleObject.new(o2, :C)
Registry.resolve(o3, "::A").should == o1
Registry.resolve(o3, "::String", false, true).should == P(:String)
end
it "should resolve instance methods with # prefix" do
o1 = ModuleObject.new(:root, :A)
o2 = ModuleObject.new(o1, :B)
o3 = ModuleObject.new(o2, :C)
o4 = MethodObject.new(o3, :methname)
Registry.resolve(o1, "B::C#methname").should == o4
Registry.resolve(o2, "C#methname").should == o4
Registry.resolve(o3, "#methname").should == o4
end
it "should resolve instance methods in the root without # prefix" do
o = MethodObject.new(:root, :methname)
Registry.resolve(:root, 'methname').should == o
end
it "should resolve superclass methods when inheritance = true" do
superyard = ClassObject.new(:root, :SuperYard)
yard = ClassObject.new(:root, :YARD)
yard.superclass = superyard
imeth = MethodObject.new(superyard, :hello)
cmeth = MethodObject.new(superyard, :class_hello, :class)
Registry.resolve(yard, "#hello", false).should be_nil
Registry.resolve(yard, "#hello", true).should == imeth
Registry.resolve(yard, "class_hello", false).should be_nil
Registry.resolve(yard, "class_hello", true).should == cmeth
end
it "should resolve mixin methods when inheritance = true" do
yard = ClassObject.new(:root, :YARD)
mixin = ModuleObject.new(:root, :Mixin)
yard.mixins(:instance) << mixin
imeth = MethodObject.new(mixin, :hello)
cmeth = MethodObject.new(mixin, :class_hello, :class)
Registry.resolve(yard, "#hello", false).should be_nil
Registry.resolve(yard, "#hello", true).should == imeth
Registry.resolve(yard, "class_hello", false).should be_nil
Registry.resolve(yard, "class_hello", true).should == cmeth
end
it "should only check 'Path' in lookup on root namespace" do
Registry.should_receive(:at).once.with('Test').and_return(true)
Registry.resolve(Registry.root, "Test")
end
it "should not perform lookup by joining namespace and name without separator" do
yard = ClassObject.new(:root, :YARD)
Registry.should_not_receive(:at).with('YARDB')
Registry.resolve(yard, 'B')
end
end
describe '.all' do
it "should return objects of types specified by arguments" do
ModuleObject.new(:root, :A)
o1 = ClassObject.new(:root, :B)
o2 = MethodObject.new(:root, :testing)
r = Registry.all(:method, :class)
r.should include(o1, o2)
end
it "should return code objects" do
o1 = ModuleObject.new(:root, :A)
o2 = ClassObject.new(:root, :B)
MethodObject.new(:root, :testing)
r = Registry.all.select {|t| NamespaceObject === t }
r.should include(o1, o2)
end
it "should allow .all to omit list" do
o1 = ModuleObject.new(:root, :A)
o2 = ClassObject.new(:root, :B)
r = Registry.all
r.should include(o1, o2)
end
end
describe '.paths' do
it "should return all object paths" do
o1 = ModuleObject.new(:root, :A)
o2 = ClassObject.new(:root, :B)
Registry.paths.should include('A', 'B')
end
end
describe '.load_yardoc' do
it "should delegate load to RegistryStore" do
store = RegistryStore.new
store.should_receive(:load).with('foo')
RegistryStore.should_receive(:new).and_return(store)
Registry.yardoc_file = 'foo'
Registry.load_yardoc
end
it "should return itself" do
Registry.load_yardoc.should == Registry
end
it "should maintain hash key equality on loaded objects" do
Registry.clear
Registry.load!(File.dirname(__FILE__) + '/serializers/data/serialized_yardoc')
baz = Registry.at('Foo#baz')
Registry.at('Foo').aliases.keys.should include(baz)
Registry.at('Foo').aliases.has_key?(baz).should == true
end
end
['load', 'load_all', 'load!'].each do |meth|
describe('.' + meth) do
it "should return itself" do
Registry.send(meth).should == Registry
end
end
end
describe '.each' do
before do
YARD.parse_string "def a; end; def b; end; def c; end"
end
after { Registry.clear }
it "should iterate over .all" do
items = []
Registry.each {|x| items << x.path }
items.sort.should == ['#a', '#b', '#c']
end
it "should include Enumerable and allow for find, select" do
Registry.find {|x| x.path == "#a" }.should be_a(CodeObjects::MethodObject)
end
end
describe '.instance' do
it "should return itself" do
Registry.instance.should == Registry
end
end
describe '.single_object_db' do
it "should default to nil" do
Registry.single_object_db.should == nil
Thread.new { Registry.single_object_db.should == nil }.join
end
end
describe 'Thread local' do
it "should maintain two Registries in separate threads" do
barrier = 0
mutex = Mutex.new
threads = []
threads << Thread.new do
Registry.clear
YARD.parse_string "# docstring 1\nclass Foo; end"
mutex.synchronize { barrier += 1 }
while barrier < 2 do
s = "barrier < 2, spinning"
end
Registry.at('Foo').docstring.should == "docstring 1"
end
threads << Thread.new do
Registry.clear
YARD.parse_string "# docstring 2\nclass Foo; end"
mutex.synchronize { barrier += 1 }
while barrier < 2 do
s = "barrier < 2, spinning"
end
Registry.at('Foo').docstring.should == "docstring 2"
end
threads.each {|t| t.join }
end
it "should allow setting of yardoc_file in separate threads" do
barrier = 0
mutex = Mutex.new
threads = []
threads << Thread.new do
Registry.yardoc_file.should == '.yardoc'
Registry.yardoc_file = 'foo'
mutex.synchronize { barrier += 1 }
while barrier == 1 do
s = "barrier = 1, spinning"
end
Registry.yardoc_file.should == 'foo'
end
threads << Thread.new do
while barrier == 0 do
s = "barrier = 0, spinning"
end
Registry.yardoc_file.should == '.yardoc'
mutex.synchronize { barrier += 1 }
Registry.yardoc_file = 'foo2'
end
threads.each {|t| t.join }
Registry.yardoc_file = Registry::DEFAULT_YARDOC_FILE
end
it "should automatically clear in new threads" do
Thread.new { Registry.all.should be_empty }.join
end
end
end
Something went wrong with that request. Please try again.