Permalink
Browse files

Beefed up equality tests and hash calculatesion for version,

specification and requirements.  Added mutex around gem path searcher
creation.


git-svn-id: svn+ssh://rubyforge.org/var/svn/rubygems/trunk@1066 3d4018f9-ac1a-0410-99e9-8a154d859a19
  • Loading branch information...
1 parent 5e563c6 commit d6dc09c87e1342de6ec57441a38f958713392f0a @jimweirich jimweirich committed Sep 18, 2006
View
27 ChangeLog
@@ -1,3 +1,30 @@
+2006-09-18 Jim Weirich <jim@weirichhouse.org>
+
+ * lib/rubygems/version.rb (Gem::Dependency::hash): Added hash code
+ calculation.
+ (Gem::Version::hash): Added hash code calculation.
+ (Gem::Requirement::hash): Added hash code calculation.
+
+ * test/test_specification.rb (TestSpecificationEquality): Added
+ tests for specification equality and hashing.
+
+ * test/test_remote_installer.rb
+ (TestRemoteInstaller::test_installer_has_proxy_uri): Added tests
+ for proper proxy initialization in RemoteFetcher.
+
+ * test/test_version_comparison.rb (TestVersionEquality): Added
+ tests for version equality and hashing.
+ (TestRequirementEquality): Added tests for requirement equality.
+
+ * lib/rubygems/specification.rb (Gem::Specification::hash): Added
+ a hash method and improved equality testing.
+
+2006-09-15 Jim Weirich <jim@weirichhouse.org>
+
+ * lib/rubygems.rb (Gem::OperationNotSupportedError::searcher):
+ Moved searcher initialization into Gem module and added Mutex
+ protection.
+
2006-08-22 Jim Weirich <jim@weirichhouse.org>
* lib/rubygems/remote_installer.rb (Gem::RemoteInstaller::download_gem):
View
10 lib/rubygems.rb
@@ -73,6 +73,9 @@ def active_gem_with_options(gem_name, version_requirements, options={})
#
module Gem
require 'rubygems/rubygems_version.rb'
+ require 'thread'
+
+ MUTEX = Mutex.new
class Exception < RuntimeError
end
@@ -162,6 +165,13 @@ def datadir(gem_name)
File.join(spec.full_gem_path, 'data', gem_name)
end
+ # Return the searcher object to search for matching gems.
+ def searcher
+ MUTEX.synchronize do
+ @searcher ||= Gem::GemPathSearcher.new
+ end
+ end
+
# Return the Ruby command to use to execute the Ruby interpreter.
def ruby
"ruby"
View
3 lib/rubygems/custom_require.rb
@@ -27,8 +27,7 @@ def require(path)
gem_original_require path
rescue LoadError => load_error
begin
- @gempath_searcher ||= Gem::GemPathSearcher.new
- if spec = @gempath_searcher.find(path)
+ if spec = Gem.searcher.find(path)
Gem.activate(spec.name, false, "= #{spec.version}")
gem_original_require path
else
View
12 lib/rubygems/specification.rb
@@ -516,11 +516,23 @@ def <=>(other)
# Tests specs for equality (across all attributes).
def ==(other)
+ other.kind_of?(self.class) && same_attributes?(other)
+ end
+
+ def same_attributes?(other)
@@attributes.each do |name, default|
return false unless self.send(name) == other.send(name)
end
true
end
+ private :same_attributes?
+
+ def hash
+ @@attributes.inject(0) { |hash_code, (name, default_value)|
+ n = self.send(name).hash
+ hash_code + n
+ }
+ end
# Export methods (YAML and Ruby code) ----------------------------
View
16 lib/rubygems/version.rb
@@ -54,6 +54,12 @@ def ==(other)
self.name = other.name and
self.version_requirements == other.version_requirements
end
+
+ def hash
+ fail
+ name.hash + version_requirements.hash
+ end
+
end
####################################################################
@@ -150,6 +156,10 @@ def <=>(other)
return r <=> v
end
+ def hash
+ to_ints.inject { |hash_code, n| hash_code + n }
+ end
+
# Return a new version object where the next to the last revision
# number is one greater. (e.g. 5.3.1 => 5.4)
def bump
@@ -300,7 +310,11 @@ def parse(str)
def <=>(other)
to_s <=> other.to_s
end
-
+
+ def hash
+ to_s.hash
+ end
+ public :hash
end
end
View
18 test/test_remote_installer.rb
@@ -14,6 +14,7 @@
class MockFetcher
def initialize(uri, proxy)
@uri = uri
+ @proxy = proxy
end
def size
@@ -62,8 +63,21 @@ def setup
@installer.instance_variable_set("@fetcher_class", MockFetcher)
end
- def test_create
- assert_not_nil(@installer)
+ def test_installer_has_proxy_uri
+ proxy = "http://user:pass@proxy.url"
+ @installer.instance_variable_set("@options", {:http_proxy => proxy})
+ MockFetcher.class_eval("def fetch_path(path); raise 'failed' unless @proxy == '#{proxy}'; end")
+
+ spec = Gem::Specification.new do |s|
+ s.version = "1.0.0"
+ s.name = "boo"
+ s.platform = Gem::Platform::RUBY
+ s.date = Time.now
+ s.summary = "Hello"
+ s.require_paths = ["."]
+ end
+
+ @installer.download_gem("dest_file", "source", spec)
end
# Make sure that the installer knows the proper list of places to go
View
42 test/test_specification.rb
@@ -268,6 +268,48 @@ def test_to_ruby
end
+class TestSpecificationEquality < Test::Unit::TestCase
+
+ def test_equals_is_true_on_same_specification
+ s = Gem::Specification.new
+ assert s == s
+ end
+
+ def test_specs_with_same_attributes_are_equal
+ s = Gem::Specification.new do |spec| spec.name = "ONE" end
+ t = Gem::Specification.new do |spec| spec.name = "ONE" end
+ assert (s == t)
+ assert (t == s)
+ end
+
+ def test_specs_with_same_attributes_have_same_hash_code
+ s = Gem::Specification.new do |spec| spec.name = "ONE" end
+ t = Gem::Specification.new do |spec| spec.name = "ONE" end
+ assert_equal s.hash, t.hash
+ end
+
+ def test_specs_with_different_attributes_are_not_equal
+ s = Gem::Specification.new do |spec| spec.name = "ONE" end
+ t = Gem::Specification.new do |spec| spec.name = "TWO" end
+ assert ! (s == t)
+ assert ! (t == s)
+ end
+
+ def test_specs_with_different_attributes_have_different_hash_codes
+ s = Gem::Specification.new do |spec| spec.name = "ONE" end
+ t = Gem::Specification.new do |spec| spec.name = "TWO" end
+ assert s.hash != t.hash
+ end
+
+ def test_equals_is_false_on_non_spec_objects
+ s = Gem::Specification.new
+ t = Object.new
+ assert ! (s == t)
+ assert ! (t == s)
+ end
+
+end
+
class TestComplexSpecification < Test::Unit::TestCase
def setup
View
58 test/test_version_comparison.rb
@@ -102,8 +102,36 @@ def test_bump_one_level
assert_equal "6", v.bump.to_s
end
end
-
+class TestVersionEquality < Test::Unit::TestCase
+ def test_same_versions_are_equal
+ v = Gem::Version.new("1.2")
+ u = Gem::Version.new("1.2")
+ assert v == u
+ assert u == v
+ end
+
+ def test_same_versions_have_same_hash
+ v = Gem::Version.new("1.2")
+ u = Gem::Version.new("1.2")
+ assert_equal v.hash, u.hash
+ end
+
+ def test_different_versions_are_not_equal
+ v = Gem::Version.new("1.2")
+ u = Gem::Version.new("1.3")
+ assert v != u
+ assert u != v
+ end
+
+ def test_difference3_versions_have_different_hash
+ v = Gem::Version.new("1.2")
+ u = Gem::Version.new("1.3")
+ assert_not_equal v.hash, u.hash
+ end
+
+end
+
class TestExtendedVersionComparisons < Test::Unit::TestCase
include VersionAsserts
@@ -208,3 +236,31 @@ def test_normalization
assert_equal ">= 1.0.4", dep.to_s
end
end
+
+class TestRequirementEquality < Test::Unit::TestCase
+ def test_same_requirements_are_equal
+ r = Gem::Requirement.new("= 1.2")
+ p = Gem::Requirement.new("= 1.2")
+ assert r == p
+ assert p == r
+ end
+
+ def test_same_requirements_have_same_hash_code
+ r = Gem::Requirement.new("= 1.2")
+ p = Gem::Requirement.new("= 1.2")
+ assert_equal r.hash, p.hash
+ end
+
+ def test_different_requirements_are_not_equal
+ r = Gem::Requirement.new("= 1.2")
+ p = Gem::Requirement.new("< 1.2")
+ assert r != p
+ assert p != r
+ end
+
+ def test_different_requirements_have_different_hash_codes
+ r = Gem::Requirement.new("= 1.2")
+ p = Gem::Requirement.new("< 1.2")
+ assert_not_equal r.hash, p.hash
+ end
+end

0 comments on commit d6dc09c

Please sign in to comment.