Commits

Michael Granger  committed 2e32ed8

Convert to Loggability for logging

  • Participants
  • Parent commits 4dcbdee

Comments (0)

Files changed (23)

-hoe-deveiate -v0.0.8
+hoe-deveiate -v0.1.1
 ruby-ldap -v0.9.12
 sequel -v3.31.0
+loggability -v0.2.3
+

File .tm_properties

 # Settings
 projectDirectory     = "$CWD"
 windowTitle          = "${CWD/^.*\///} — «$TM_DISPLAYNAME»"
-excludeInFileChooser = "{$exclude,.hg}"
+excludeInFileChooser = "{$exclude,.hg,pkg}"
 
 [ source.ruby ]
 softTabs         = false
 kick-ass database library.
 
 
-
-
 == Contributing
 
 You can check out the current development source
 
 == License
 
-Copyright (c) 2008-2011, Michael Granger and Mahlon E. Smith
+Copyright (c) 2008-2012, Michael Granger and Mahlon E. Smith
 All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-This software includes some code from the Sequel database toolkit, used under 
+This software includes some code from the Sequel database toolkit, used under
 the following license terms:
 
   Copyright (c) 2007-2008 Sharon Rosner

File lib/treequel.rb

 require 'ldap/schema'
 require 'ldap/control'
 
-require 'logger'
+require 'loggability'
 require 'pathname'
 
 require 'uri'
 
 # A library for interacting with LDAP modelled after Sequel[http://sequel.rubyforge.org/].
 module Treequel
+	extend Loggability
+
+
+	# Loggability API -- set up a Logger for all Treequel-related logging
+	log_as :treequel
+
 
 	# Library version
 	VERSION = '1.8.6'
 
 
 	#
-	# :section: Logging
-	#
-
-	# Log levels
-	LOG_LEVELS = {
-		'debug' => Logger::DEBUG,
-		'info'  => Logger::INFO,
-		'warn'  => Logger::WARN,
-		'error' => Logger::ERROR,
-		'fatal' => Logger::FATAL,
-	}.freeze
-	LOG_LEVEL_NAMES = LOG_LEVELS.invert.freeze
-
-	@default_logger = Logger.new( $stderr )
-	@default_logger.level = $DEBUG ? Logger::DEBUG : Logger::WARN
-
-	@default_log_formatter = Treequel::LogFormatter.new( @default_logger )
-	@default_logger.formatter = @default_log_formatter
-
-	@logger = @default_logger
-
-
-	class << self
-		# The log formatter that will be used when the logging subsystem is reset
-		attr_accessor :default_log_formatter
-
-		# The logger that will be used when the logging subsystem is reset
-		attr_accessor :default_logger
-
-		# The logger that's currently in effect
-		attr_accessor :logger
-		alias_method :log, :logger
-		alias_method :log=, :logger=
-	end
-
-
-	### Reset the global logger object to the default
-	def self::reset_logger
-		self.logger = self.default_logger
-		self.logger.level = Logger::WARN
-		self.logger.formatter = self.default_log_formatter
-	end
-
-
-	### Returns +true+ if the global logger has not been set to something other than
-	### the default one.
-	def self::using_default_logger?
-		return self.logger == self.default_logger
-	end
-
-
-	#
 	# :section:
 	#
 
 	end
 
 
+	### Reset the logger associated with Treequel. Backward-compatibility method.
+	def self::reset_logger
+		Treequel.logger = Treequel.default_logger
+		Treequel.logger.formatter = nil
+		Treequel.logger.output_to( $stderr )
+		Treequel.logger.level = :fatal
+	end
+
+
+	### Returns +true+ if the current logger for Treequel is the default one.
+	### Backward-compatibility method.
+	def self::using_default_logger?
+		return Loggability[ Treequel ] == Treequel.default_logger
+	end
+
+
 	# Now load the rest of the library
 	require 'treequel/exceptions'
 	require 'treequel/directory'

File lib/treequel/branch.rb

 # for the entries below itself, and how to search for those entries.
 class Treequel::Branch
 	include Comparable,
-	        Treequel::Loggable,
 	        Treequel::Constants,
 	        Treequel::Constants::Patterns,
 	        Treequel::HashUtilities
 
-	extend Treequel::Delegation,
+	extend Loggability,
+	       Treequel::Delegation,
 	       Treequel::AttributeDeclarations
 
 
+	# Loggability API -- Log to the Treequel module's logger
+	log_to :treequel
+
+
 	# The default width of LDIF output
 	DEFAULT_LDIF_WIDTH = 70
 

File lib/treequel/branchcollection.rb

 # A Treequel::BranchCollection is a union of Treequel::Branchset
 # objects, suitable for performing operations on multiple branches
 # of the directory at once.
-# 
+#
 # For example, if you have hosts under ou=Hosts in two different
 # subdomains (e.g., acme.com, seattle.acme.com, and newyork.acme.com),
 # and you want to search for a host by its CN, you could do so like
 # this:
-# 
+#
 #   # Top-level hosts, and those in the 'seattle' subdomain, but not
 #   # those in the 'newyork' subdomain:
 #   west_coast_hosts = dir.ou( :hosts ) + dir.dc( :seattle ).ou( :hosts )
 #   west_coast_www_hosts = west_coast_hosts.filter( :cn => 'www' )
-#   
+#
 #   # And one that includes hosts in all three DCs:
 #   all_hosts = west_coast_hosts + dir.dc( :newyork ).ou( :hosts )
 #   all_ns_hosts = all_hosts.filter( :cn => 'ns*' )
-# 
+#
 # Note that you could accomplish most of what BranchCollection does
 # using filters, but some people might find this a bit more readable.
 class Treequel::BranchCollection
 	include Enumerable,
-	        Treequel::Loggable,
 	        Treequel::Constants
 
-	extend Treequel::Delegation
+	extend Loggability,
+	       Treequel::Delegation
+
+
+	# Loggability API -- Log to the Treequel module's logger
+	log_to :treequel
 
 
 	#################################################################

File lib/treequel/branchset.rb

 # Branchsets are Enumerable objects, so they can be manipulated using any of the 
 # Enumerable methods, such as map, inject, etc.
 class Treequel::Branchset
+	extend Loggability
 	include Enumerable,
-	        Treequel::Loggable,
 	        Treequel::Constants,
 	        Treequel::Control
 
+	# Loggability API -- Log to the Treequel module's logger
+	log_to :treequel
+
 	# The default scope to use when searching if none is specified
 	DEFAULT_SCOPE = :subtree
 	DEFAULT_SCOPE.freeze

File lib/treequel/directory.rb

 # The object in Treequel that represents a connection to a directory, the
 # binding to that directory, and the base from which all DNs start.
 class Treequel::Directory
-	include Treequel::Loggable,
-	        Treequel::Constants,
+	include Treequel::Constants,
 	        Treequel::HashUtilities
 
-	extend Treequel::Delegation
+	extend Loggability,
+	       Treequel::Delegation
+
+	# Loggability API -- Log to the Treequel module's logger
+	log_to :treequel
+
 
 	# The default directory options
 	DEFAULT_OPTIONS = {
 	end
 
 
-	### Copy constructor -- the duplicate should have a distinct connection, bound user, 
+	### Copy constructor -- the duplicate should have a distinct connection, bound user,
 	### and should have a distinct copy of the +original+'s registered controls.
 	def initialize_copy( original )
 		@conn       = nil

File lib/treequel/filter.rb

 #   value      = AttributeValue from Section 4.1.6 of [1]
 # 
 class Treequel::Filter
-	include Treequel::Loggable,
-	        Treequel::Constants::Patterns
+	extend Loggability
+	include Treequel::Constants::Patterns
+
+
+	# Loggability API -- Log to the Treequel module's logger
+	log_to :treequel
+
 
 	### Filter list component of a Treequel::Filter.
 	class FilterList
-		include Treequel::Loggable
+		extend Loggability
+
+		# Loggability API -- Log to the Treequel module's logger
+		log_to :treequel
 
 		### Create a new filter list with the given +filters+ in it.
 		def initialize( *filters )
 	### An abstract class for filter components.
 	### Subclass and override #to_s to implement a custom Component class.
 	class Component
-		include Treequel::Loggable
+		extend Loggability
+
+		# Loggability API -- Log to the Treequel module's logger
+		log_to :treequel
 
 		# Hide this class's new method
 		private_class_method :new
 
+
 		### Inherited hook: re-expose inheriting class's .new method
 		def self::inherited( klass )
 			klass.module_eval( 'public_class_method :new' )
 				raise Treequel::ExpressionError,
 					"unable to parse %p as a substring literal" % [ literal ]
 
-			Treequel.logger.debug "  parsed substring literal as: %p" % [ match.captures ]
+			self.log.debug "  parsed substring literal as: %p" % [ match.captures ]
 			return self.new( *(match.captures.values_at(1,3,2)) )
 		end
 
 	### Turn the specified filter +expression+ into a Treequel::Filter::Component
 	### object and return it.
 	def self::parse_expression( expression )
-		Treequel.logger.debug "Parsing expression %p" % [ expression ]
+		self.log.debug "Parsing expression %p" % [ expression ]
 		expression = expression[0] if expression.is_a?( Array ) && expression.length == 1
 
 		case expression
 	### Turn the specified expression Array into a Treequel::Filter::Component object
 	### and return it.
 	def self::parse_array_expression( expression )
-		Treequel.logger.debug "Parsing Array expression %p" % [ expression ]
+		self.log.debug "Parsing Array expression %p" % [ expression ]
 
 		case
 
 		# [ ] := '(objectClass=*)'
 		when expression.empty?
-			Treequel.logger.debug "  empty expression -> objectClass presence item component"
+			self.log.debug "  empty expression -> objectClass presence item component"
 			return Treequel::Filter::PresentItemComponent.new
 
 		# Collection of subfilters
 		# [ [:uid, 'mahlon'], [:employeeNumber, 20202] ]
 		when expression.all? {|elem| elem.is_a?(Array) }
-			Treequel.logger.debug "  parsing array of subfilters"
+			self.log.debug "  parsing array of subfilters"
 			filters = expression.collect {|exp| Treequel::Filter.new(exp) }
 			if filters.length > 1
 				return Treequel::Filter::AndComponent.new( filters )
 	### Parse one or more tuples contained in a Hash into an ANDed set of 
 	### Treequel::Filter::Components and return it.
 	def self::parse_hash_expression( expression )
-		Treequel.logger.debug "Parsing Hash expression %p" % [ expression ]
+		self.log.debug "Parsing Hash expression %p" % [ expression ]
 
 		filterlist = expression.collect do |key, expr|
-			Treequel.logger.debug "  adding %p => %p to the filter list" % [ key, expr ]
+			self.log.debug "  adding %p => %p to the filter list" % [ key, expr ]
 			if expr.respond_to?( :fetch )
 				if expr.respond_to?( :length ) && expr.length > 1
-					Treequel.logger.debug "    ORing together %d subfilters since %p has indices" %
+					self.log.debug "    ORing together %d subfilters since %p has indices" %
 						[ expr.length, expr ]
 					subfilters = expr.collect {|val| Treequel::Filter.new(key, val) }
 					Treequel::Filter.new( :or, subfilters )
 				else
-					Treequel.logger.debug "    unwrapping singular subfilter"
+					self.log.debug "    unwrapping singular subfilter"
 					Treequel::Filter.new([ key.to_sym, expr.first ])
 				end
 			else
-				Treequel.logger.debug "    value is a scalar; creating a single filter"
+				self.log.debug "    value is a scalar; creating a single filter"
 				Treequel::Filter.new( key.to_sym, expr )
 			end
 		end
 	### Parse a tuple of the form: [ Symbol, Object ] into a Treequel::Filter::Component
 	### and return it.
 	def self::parse_tuple_array_expression( expression )
-		Treequel.logger.debug "Parsing tuple Array expression %p" % [ expression ]
+		self.log.debug "Parsing tuple Array expression %p" % [ expression ]
 
 		case expression[1]
 
 			return self.parse_logical_array_expression( *expression )
 
 		when Range
-			Treequel.logger.debug "  two ANDed item expressions from a Range"
+			self.log.debug "  two ANDed item expressions from a Range"
 			attribute = expression[0]
 			range = expression[1]
 			left = "#{attribute}>=#{range.begin}"
 		# [ :attribute, 'value' ]  := '(attribute=value)'
 		# when String, Symbol, Numeric, Time
 		else
-			Treequel.logger.debug "  item expression from a %p" % [ expression[1].class ]
+			self.log.debug "  item expression from a %p" % [ expression[1].class ]
 			return self.parse_item_component( *expression )
 		end
 	end
 	### Break down the given +expression+ as a logical (AND, OR, or NOT)
 	### filter component and return it.
 	def self::parse_logical_array_expression( op, *components )
-		Treequel.logger.debug "Parsing logical %p expression with components: %p" %
+		self.log.debug "Parsing logical %p expression with components: %p" %
 			[ op, components ]
 
 		compclass = LOGICAL_COMPONENTS[ op ] or
 			 	[ op, LOGICAL_COMPONENTS.keys ]
 
 		filterlist = components.collect do |filterexp|
-			Treequel.logger.debug "  making %p into a component" % [ filterexp ]
+			self.log.debug "  making %p into a component" % [ filterexp ]
 			Treequel::Filter.new( filterexp )
 		end.flatten
 
 
 	### Parse an item component from the specified +attribute+ and +value+
 	def self::parse_item_component( attribute, value )
-		Treequel.logger.debug "  tuple expression (%p=%p)-> item component" %
+		self.log.debug "  tuple expression (%p=%p)-> item component" %
 			[ attribute, value ]
 
 		case
 
 	### Parse a Sequel::SQL::Expression as a Treequel::Filter::Component and return it.
 	def self::parse_sequel_expression( expression )
-		Treequel.logger.debug "  parsing Sequel expression: %p" % [ expression ]
+		self.log.debug "  parsing Sequel expression: %p" % [ expression ]
 
 		if expression.respond_to?( :op )
 			op = expression.op.to_s.downcase.to_sym
 				# Turn :sn.like( 'bob' ) into (cn~=bob) 'cause it has no asterisks
 				if op == :like 
 					if value.index( '*' )
-						Treequel.logger.debug \
+						self.log.debug \
 							"    turning a LIKE expression with an asterisk into a substring filter"
 						return Treequel::Filter::SubstringItemComponent.new( attribute, value )
 					else
-						Treequel.logger.debug \
+						self.log.debug \
 							"    turning a LIKE expression with no wildcards into an 'approx' filter"
 						equivalent = :approx
 					end
 				return Treequel::Filter::NotComponent.new( contents )
 
 			elsif op == :'not like'
-				Treequel.logger.debug "  making a NOT LIKE expression out of: %p" % [ expression ]
+				self.log.debug "  making a NOT LIKE expression out of: %p" % [ expression ]
 				attribute, value = *expression.args
 				component = nil
 

File lib/treequel/mixins.rb

 	### Add logging to a Treequel class. Including classes get #log and #log_debug methods.
 	module Loggable
 
-		### A logging proxy class that wraps calls to the logger into calls that include
-		### the name of the calling class.
-		class ClassNameProxy
-
-			### Create a new proxy for the given +klass+.
-			def initialize( klass, force_debug=false )
-				@classname   = klass.name
-				@force_debug = force_debug
-			end
-
-			### Delegate debug messages to the global logger with the appropriate class name.
-			def debug( msg=nil, &block )
-				Treequel.logger.add( Logger::DEBUG, msg, @classname, &block )
-			end
-
-			### Delegate info messages to the global logger with the appropriate class name.
-			def info( msg=nil, &block )
-				return self.debug( msg, &block ) if @force_debug
-				Treequel.logger.add( Logger::INFO, msg, @classname, &block )
-			end
-
-			### Delegate warn messages to the global logger with the appropriate class name.
-			def warn( msg=nil, &block )
-				return self.debug( msg, &block ) if @force_debug
-				Treequel.logger.add( Logger::WARN, msg, @classname, &block )
-			end
-
-			### Delegate error messages to the global logger with the appropriate class name.
-			def error( msg=nil, &block )
-				return self.debug( msg, &block ) if @force_debug
-				Treequel.logger.add( Logger::ERROR, msg, @classname, &block )
-			end
-
-			### Delegate fatal messages to the global logger with the appropriate class name.
-			def fatal( msg=nil, &block )
-				Treequel.logger.add( Logger::FATAL, msg, @classname, &block )
-			end
-
-		end # ClassNameProxy
-
-		#########
-		protected
-		#########
-
-		### Copy constructor -- clear the original's log proxy.
-		def initialize_copy( original )
-			@log_proxy = @log_debug_proxy = nil
-			super
-		end
-
-		### Return the proxied logger.
-		def log
-			@log_proxy ||= ClassNameProxy.new( self.class )
-		end
-
-		### Return a proxied "debug" logger that ignores other level specification.
-		def log_debug
-			@log_debug_proxy ||= ClassNameProxy.new( self.class, true )
+		### Inclusion callback -- extend including modules with Loggability instead for
+		### backward-compatibility.
+		def self::included( mod )
+			mod.extend( Loggability )
+			mod.log_to( :treequel )
 		end
 
 	end # module Loggable

File lib/treequel/model.rb

 
 # An object interface to LDAP entries.
 class Treequel::Model < Treequel::Branch
+	extend Loggability
+
 	require 'treequel/model/objectclass'
 	require 'treequel/model/errors'
 	require 'treequel/model/schemavalidations'
 
-	include Treequel::Loggable,
-	        Treequel::Constants,
+	include Treequel::Constants,
 	        Treequel::Normalization,
 	        Treequel::Constants::Patterns,
 	        Treequel::Model::SchemaValidations
 
 
+	# Loggability API -- Log to the Treequel module's logger
+	log_to :treequel
+
+
 	# A prototype Hash that autovivifies its members as Sets, for use in
 	# the objectclass_registry and the base_registry
 	SET_HASH = Hash.new {|h,k| h[k] = Set.new }

File lib/treequel/model/errors.rb

 #     CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 # 
 class Treequel::Model::Errors < ::Hash
-	include Treequel::HashUtilities,
-	        Treequel::Loggable
+	extend Loggability
+	include Treequel::HashUtilities
+
+	# Loggability API -- Log to the Treequel module's logger
+	log_to :treequel
+
 
 	# The word to use between attributes in error messages
 	ATTRIBUTE_CONJUNCTION = ' and '

File lib/treequel/schema.rb

 # Please see the file LICENSE in the base directory for licensing details.
 #
 class Treequel::Schema
-	include Treequel::Loggable,
-	        Treequel::Constants::Patterns
+	extend Loggability
+	include Treequel::Constants::Patterns
+
+	# Loggability API -- Log to the Treequel module's logger
+	log_to :treequel
 
 	require 'treequel/schema/table'
 	require 'treequel/schema/objectclass'

File lib/treequel/schema/attributetype.rb

 # Please see the file LICENSE in the base directory for licensing details.
 #
 class Treequel::Schema::AttributeType
-	include Treequel::Loggable,
-	        Treequel::Normalization,
+	include Treequel::Normalization,
 	        Treequel::Constants::Patterns
 
-	extend Treequel::AttributeDeclarations
+	extend Loggability,
+	       Treequel::AttributeDeclarations
+
+	# Loggability API -- Log to the Treequel module's logger
+	log_to :treequel
+
 
 	# Regex for splitting a syntax OID from its length specifier
 	OID_SPLIT_PATTERN = /

File lib/treequel/schema/ldapsyntax.rb

 
 # This is a class for representing ldapSyntax declarations in a Treequel::Schema.
 class Treequel::Schema::LDAPSyntax
-	include Treequel::Loggable,
-	        Treequel::Constants::Patterns
+	include Treequel::Constants::Patterns
+	extend Loggability,
+	       Treequel::AttributeDeclarations
 
-	extend Treequel::AttributeDeclarations
+
+	# Loggability API -- Log to the Treequel module's logger
+	log_to :treequel
 
 
 	#############################################################

File lib/treequel/schema/matchingrule.rb

 
 # This is a class for representing matchingRule declarations in a Treequel::Schema.
 class Treequel::Schema::MatchingRule
-	include Treequel::Loggable,
-	        Treequel::Constants::Patterns
+	include Treequel::Constants::Patterns
+	extend Loggability,
+	       Treequel::AttributeDeclarations
 
-	extend Treequel::AttributeDeclarations
+
+	# Loggability API -- Log to the Treequel module's logger
+	log_to :treequel
 
 
 	#############################################################

File lib/treequel/schema/matchingruleuse.rb

 
 # This is a class for representing matchingRuleUse declarations in a Treequel::Schema.
 class Treequel::Schema::MatchingRuleUse
-	include Treequel::Loggable,
-	        Treequel::Constants::Patterns
+	include Treequel::Constants::Patterns
 
-	extend Treequel::AttributeDeclarations
+	extend Loggability,
+	       Treequel::AttributeDeclarations
+
+
+	# Loggability API -- Log to the Treequel module's logger
+	log_to :treequel
 
 
 	#############################################################

File lib/treequel/schema/objectclass.rb

 
 	### objectClass entries in a Treequel::Schema.
 	class ObjectClass
-		include Treequel::Loggable,
-		        Treequel::Constants::Patterns
+		include Treequel::Constants::Patterns
 
-		extend Treequel::AttributeDeclarations
+		extend Loggability,
+		       Treequel::AttributeDeclarations
 
 
+		# Loggability API -- Log to the Treequel module's logger
+		log_to :treequel
+
+
+		# Hide the constructor
 		private_class_method :new
 
 		# The 'kind' of objectClasses which don't specify a 'kind' explicitly

File lib/treequel/schema/table.rb

 # This is an object that is used to store LDAP schema information in a 
 # case-insensitive table.
 class Treequel::Schema::Table
-	extend Forwardable
+	extend Forwardable,
+	       Loggability
 	include Enumerable,
-	        Treequel::Loggable,
 	        Treequel::Normalization,
 	        Treequel::Constants::Patterns
 
+	# Loggability API -- Log to the Treequel module's logger
+	log_to :treequel
+
+
 	# The list of methods that should be delegated through the key-normalization
 	# method.
 	KEYED_METHODS = [ :"[]", :"[]=", :delete, :fetch, :key?, :has_key?, :include?,

File spec/lib/helpers.rb

 
 	### Reset the logging subsystem to its default state.
 	def reset_logging
-		Treequel.reset_logger
+		Treequel.logger = Treequel.default_logger
+		Loggability.formatter = nil
+		Loggability.output_to( $stderr )
+		Loggability.level = :fatal
 	end
 
 
 	### Alter the output of the default log formatter to be pretty in SpecMate output
-	def setup_logging( level=Logger::FATAL )
-
-		# Turn symbol-style level config into Logger's expected Fixnum level
-		if Treequel::LOG_LEVELS.key?( level.to_s )
-			level = Treequel::LOG_LEVELS[ level.to_s ]
-		end
-
-		logger = Logger.new( $stderr )
-		Treequel.logger = logger
-		Treequel.logger.level = level
+	def setup_logging( level=:fatal )
 
 		# Only do this when executing from a spec in TextMate
 		if ENV['HTML_LOGGING'] || (ENV['TM_FILENAME'] && ENV['TM_FILENAME'] =~ /_spec\.rb/)
-			Thread.current['logger-output'] = []
-			logdevice = ArrayLogger.new( Thread.current['logger-output'] )
-			Treequel.logger = Logger.new( logdevice )
-			# Treequel.logger.level = level
-			Treequel.logger.formatter = Treequel::HtmlLogFormatter.new( logger )
+			logarray = []
+			Thread.current['logger-output'] = logarray
+			Loggability.output_to( logarray )
+			Loggability.format_as( :html )
+			Loggability.level = :debug
+		else
+			Loggability.level = level
 		end
 	end
 

File spec/treequel/directory_spec.rb

 	describe "instances with a connection" do
 
 		before( :each ) do
-			@conn = mock( "ldap connection", :bound? => false )
-
-			@dir = Treequel::Directory.new( @options )
+			@dir = Treequel.directory( TEST_LDAPURI )
 			@dir.instance_variable_set( :@conn, @conn )
-
-			@schema = mock( "Directory schema" )
-			@conn.stub( :schema ).and_return( :the_schema )
-			Treequel::Schema.stub( :new ).with( :the_schema ).and_return( @schema )
-			@schema.stub( :attribute_types ).and_return({ :cn => :a_value, :ou => :a_value })
 		end
 
 		it "can bind with the given user DN and password" do
 			@conn.stub( :search_ext2 ).and_raise( LDAP::ResultError.new("Can't contact LDAP server") )
 
 			second_conn = mock( "LDAP connection", :set_option => true, :bound? => false )
-			LDAP::Conn.should_receive( :new ).and_return( second_conn )
+			LDAP::SSLConn.should_receive( :new ).and_return( second_conn )
 			second_conn.should_receive( :search_ext2 ).and_return([])
 
 			already_tried_reconnect = false
 		end
 
 		it "re-raises an exception rescued during a reconnect as a RuntimeError" do
-			LDAP::Conn.should_receive( :new ).
+			LDAP::SSLConn.should_receive( :new ).
 				and_raise( LDAP::ResultError.new("Can't contact LDAP server") )
 
 			expect {
 
 
 		it "doesn't retain its connection when duplicated" do
+			LDAP::SSLConn.stub( :new ).and_return do
+				mock( "LDAP connection", :set_option => true, :bound? => false )
+			end
+
 			@dir.dup.conn.should_not equal( @dir.conn )
 		end
 
 		end
 
 		it "can fetch the server's schema" do
-			@conn.should_receive( :schema ).and_return( :the_schema )
-			Treequel::Schema.should_receive( :new ).with( :the_schema ).
-				and_return( :the_parsed_schema )
-			@dir.schema.should == :the_parsed_schema
+			@dir.schema.should be_a( Treequel::Schema )
 		end
 
 		it "creates branches for messages that match valid attributeType OIDs" do
-			@schema.should_receive( :attribute_types ).
-				and_return({ :cn => :a_value, :ou => :a_value })
-
-			@dir.stub( :bound? ).and_return( false )
 			rval = @dir.ou( :people )
 			rval.dn.downcase.should == TEST_PEOPLE_DN.downcase
 		end
 
 		it "doesn't create branches for messages that don't match valid attributeType OIDs" do
-			@schema.should_receive( :attribute_types ).
-				and_return({ :cn => :a_value, :ou => :a_value })
-
 			expect { @dir.void('sbc') }.to raise_error( NoMethodError )
 		end
 

File spec/treequel/mixins_spec.rb

 
 	describe Treequel::Loggable, "mixed into a class" do
 		before(:each) do
-			@logfile = StringIO.new('')
-			Treequel.logger = Logger.new( @logfile )
+			@log_output = []
+			Treequel.logger.output_to( @log_output )
+			Treequel.logger.level = :debug
 
 			@test_class = Class.new do
 				include Treequel::Loggable
 				def log_test_message( level, msg )
 					self.log.send( level, msg )
 				end
-
-				def logdebug_test_message( msg )
-					self.log_debug.debug( msg )
-				end
 			end
 			@obj = @test_class.new
 		end
 
 		it "is able to output to the log via its #log method" do
 			@obj.log_test_message( :debug, "debugging message" )
-			@logfile.rewind
-			@logfile.read.should =~ /debugging message/
-		end
-
-		it "is able to output to the log via its #log_debug method" do
-			@obj.logdebug_test_message( "sexydrownwatch" )
-			@logfile.rewind
-			@logfile.read.should =~ /sexydrownwatch/
+			@log_output.last.should =~ /debugging message/i
 		end
 	end
 

File spec/treequel_spec.rb

 	end
 
 	it "should know if its default logger is replaced" do
-		Treequel.reset_logger
-		Treequel.should be_using_default_logger
-		Treequel.logger = Logger.new( $stderr )
-		Treequel.should_not be_using_default_logger
+		begin
+			Treequel.reset_logger
+			Treequel.should be_using_default_logger
+			Treequel.logger = Logger.new( $stderr )
+			Treequel.should_not be_using_default_logger
+		ensure
+			Treequel.reset_logger
+		end
 	end
 
 
 	end
 
 
-	describe " logging subsystem" do
-		before(:each) do
-			Treequel.reset_logger
-		end
-
-		after(:each) do
-			Treequel.reset_logger
-		end
-
-
-		it "has the default logger instance after being reset" do
-			Treequel.logger.should equal( Treequel.default_logger )
-		end
-
-		it "has the default log formatter instance after being reset" do
-			Treequel.logger.formatter.should equal( Treequel.default_log_formatter )
-		end
-
-	end
-
-
-	describe " logging subsystem with new defaults" do
-		before( :all ) do
-			@original_logger = Treequel.default_logger
-			@original_log_formatter = Treequel.default_log_formatter
-		end
-
-		after( :all ) do
-			Treequel.default_logger = @original_logger
-			Treequel.default_log_formatter = @original_log_formatter
-		end
-
-
-		it "uses the new defaults when the logging subsystem is reset" do
-			logger = double( "dummy logger" ).as_null_object
-			formatter = mock( "dummy logger" )
-
-			Treequel.default_logger = logger
-			Treequel.default_log_formatter = formatter
-
-			logger.should_receive( :formatter= ).with( formatter )
-
-			Treequel.reset_logger
-			Treequel.logger.should equal( logger )
-		end
-
-	end
-
 end
 
 # vim: set nosta noet ts=4 sw=4: