#!/usr/bin/env ruby require 'test/unit' currentPath = File.dirname(__FILE__) require File.join( currentPath, '../../lib/masterview/exceptions' ) require File.join( currentPath, '../../lib/masterview/directive_metadata' ) require File.join( currentPath, '../../lib/masterview/directive_load_path' ) DEBUG_TRACE = false #test dev hack class TestDirectiveLoadPath < Test::Unit::TestCase CurrentPath = File.dirname(__FILE__) MVTestDir = File.expand_path( File.join(CurrentPath, '..' ) ) TestFixturesDir = "#{MVTestDir}/fixtures" TestDirectivesDir = "#{MVTestDir}/fixtures/directives" MVInstallDir = File.expand_path( File.join(CurrentPath, '../../lib/masterview' ) ) BuiltinDirectivesDir = "#{MVInstallDir}/directives" PathOptionsMasterviewDirectivesAbbrev = { :use_masterview_namespace => true } PathOptionsMasterviewDirectivesFull = { :default => {:namespace => 'mv',}, :use_masterview_namespace => true } PathOptionsExtensionsDirectivesAbbrev = { :default => { :namespace => 'mvx'}, } PathOptionsExtensionsDirectivesFull = { :default => { :namespace => 'mvx'}, :use_masterview_namespace=>false } # test subjects PathEntry = MasterView::DirectiveLoadPath::PathEntry Path = MasterView::DirectiveLoadPath::Path SingletonValueClasses = [ Symbol, TrueClass, FalseClass, NilClass ] # we don't care what options deep_copy did on these def check_options_copy(original, copy) assert_not_same original, copy, "Options copy not different: original=#{original.object_id}, copy=#{copy.object_id}" original.each_pair { | key, originalValue | copied_value = copy[key] if originalValue.is_a?(Hash) assert_not_same originalValue, copied_value, "Options copy not different for key #{key}: original=#{originalValue.object_id}, copy=#{copied_value.object_id}" check_options_copy(originalValue, copied_value) else assert_equal originalValue, copied_value if ! SingletonValueClasses.include?( originalValue.class) assert_not_same originalValue, copied_value, "Options copy not different for key #{key}: original=#{originalValue.object_id}, copy=#{copied_value.object_id}" end end } end def check_path_copy(original, copy) assert_not_same original, copy, "Path copy not different: original=#{original.object_id}, copy=#{copy.object_id}" original.each_index { | index | dpe_original = original[index] dpe_copy = copy[index] assert_not_same dpe_original, dpe_copy assert_equal dpe_original.dir_path, dpe_copy.dir_path, 'path dir should be equal' assert_not_same dpe_original.dir_path, dpe_copy.dir_path, 'path dir should not be the same object' check_options_copy(dpe_original.options, dpe_copy.options) } end def test_path_entry_construction STDOUT.puts "\n------- test_path_entry --------" if DEBUG_TRACE dir_path = BuiltinDirectivesDir dpe = PathEntry.new(dir_path) STDOUT.puts "...#{dpe.inspect}" if DEBUG_TRACE assert_equal BuiltinDirectivesDir, dpe.dir_path assert dpe.options.empty?, 'Default is empty options' assert ! dpe.use_masterview_namespace, 'Only builtin MV directives use mv: namespace' assert dpe.use_extensions_namespace, 'Addond MV directives use mvx: namespace by default' assert dpe.metadata_defaults.empty?, 'Default is empty metadata defaults' options = PathOptionsMasterviewDirectivesAbbrev dpe = PathEntry.new(dir_path, options) STDOUT.puts "...#{dpe.inspect}" if DEBUG_TRACE assert_equal options.size, dpe.options.size check_options_copy( options, dpe.options ) # 'PathEntry should always keep its own copy of options' assert dpe.use_masterview_namespace, 'Builtin MV directives use mv: namespace' dir_path = 'foo' options = {:default=>{}, } dpe = PathEntry.new(dir_path, options) STDOUT.puts "...#{dpe.inspect}" if DEBUG_TRACE assert_equal dir_path, dpe.dir_path assert_equal options.size, dpe.options.size check_options_copy( options, dpe.options ) # 'PathEntry should always keep its own copy of options' assert ! dpe.use_masterview_namespace, 'Only builtin MV directives use mv: namespace' assert dpe.use_extensions_namespace, 'Addond MV directives use mvx: namespace by default' assert dpe.metadata_defaults.empty?, 'Default is empty metadata defaults' dir_path = TestDirectivesDir options = {:default=>{ :namespace => 'mvx'},:use_masterview_namespace=>false } dpe = PathEntry.new(dir_path, options) STDOUT.puts "...#{dpe.inspect}" if DEBUG_TRACE assert_equal dir_path, dpe.dir_path assert_equal options.size, dpe.options.size check_options_copy( options, dpe.options ) # 'PathEntry should always keep its own copy of options' assert ! dpe.use_masterview_namespace, 'Only builtin MV directives use mv: namespace' assert dpe.use_extensions_namespace, 'Addon MV directives use mvx: namespace by default' assert_equal 1, dpe.metadata_defaults.size, "Unexpected metadata defaults: #{dpe.options.inspect}" end def test_path_entry_validation STDOUT.puts "\n------- test_path_entry_validation --------" if DEBUG_TRACE dir_path = BuiltinDirectivesDir dpe = PathEntry.new(dir_path) dpe.validate dir_path = 'foo' dpe = PathEntry.new(dir_path) #assert_raise( MasterView::InvalidPathError ) { dpe.validate } #, 'Nonexistent path should cause error' assert_raise( MasterView::InvalidDirectivePathError ) { dpe.validate } #, 'Nonexistent path should cause error' begin dpe.validate rescue MasterView::InvalidDirectivePathError => ex assert_same dpe.dir_path, ex.path # MasterView::InvalidPathError info assert_same dpe, ex.path_entry # MasterView::InvalidDirectivePathError info assert_not_nil ex.message end end def test_path_entry_copy STDOUT.puts "\n------- test_path_entry_copy --------" if DEBUG_TRACE dir_path = 'foo' options = { :default => { :namespace => 'mvx', :description => 'TEST'}, :use_masterview_namespace=>false } dpe = PathEntry.new(dir_path, options) copy = dpe.deep_copy assert_not_same dpe, copy check_options_copy( options, dpe.options ) # 'PathEntry should always keep its own copy of options' check_options_copy( options, copy.options ) # not what we started with check_options_copy( dpe.options, copy.options ) # and not the copied guy #test the test checker itself - verify that the checker detects non-copies assert_raise( Test::Unit::AssertionFailedError ) { check_options_copy( options, options) } # verify that un-doing the nested copy gets caught copy.options[:default] = dpe.options[:default] assert_raise( Test::Unit::AssertionFailedError ) { check_options_copy( copy.options, dpe.options ) } end def test_path_ops STDOUT.puts "\n------- test_path_ops --------" if DEBUG_TRACE path = Path.new dir_paths = [] assert path.empty? assert_equal 0, path.size # verify that we can append a PathEntry dir_path1 = 'foo' dir_paths << dir_path1 dpe1 = PathEntry.new(dir_path1) path << dpe1 assert_equal dir_paths.size, path.size assert_same dpe1, path[0] # verify that we can append a string dir_path2 = 'bar' dir_paths << dir_path2 path << dir_path2 assert_equal dir_paths.size, path.size assert_equal dir_path2, path[-1].dir_path # verify obscure compat support that probably never left Deb's machine dir_path3 = 'wingding' options3 = { :default => { :namespace => 'test' } } dir_paths << dir_path3 path << [dir_path3, options3] assert_equal dir_paths.size, path.size assert_equal dir_path3, path[-1].dir_path assert_equal options3, path[-1].options assert_not_same options3, path[-1].options # verify enumerating count = 0 path.each { | dpe | assert dir_paths.include?( dpe.dir_path ) dpe.normalize # set this up for the following test count += 1 } assert_equal dir_paths.size, count # we did normalization on the entries in the preceding assert path.include?(path[-1].dir_path), 'Expanded path should be found' assert path.include?(dir_path3), 'Original rel path should also be matched' # verify (deep) copy path_copy = path.copy check_path_copy(path, path_copy) end def test_path_registry STDOUT.puts "\n------- test_path_registry --------" if DEBUG_TRACE # normal sequence is for client app to append entries, then MV::Initializer cleans up path = Path.new path << PathEntry.new(BuiltinDirectivesDir, PathOptionsMasterviewDirectivesAbbrev) path[-1].validate # this is a legit entry path << PathEntry.new('bar') assert_raise( MasterView::InvalidDirectivePathError ) { path[1].validate } #, 'Nonexistent path should cause error' # oh, just give up - this works standalone, but screws up the system state when we run entire suite if true return end # Masterview::Initializer cleans up the path, validates and normalizes, and registers # But if we run this during test suite execution we don't know the state of the system, so be careful here real_load_path_values = MasterView::DirectiveLoadPath.path_registry if ! real_load_path_values.empty? assert real_load_path_values.include?(:default) # the default_load_path specs assert real_load_path_values.include?(:current) # the current load path end STDOUT.puts "...DirectiveLoadPath.default_path_specs=#{MasterView::DirectiveLoadPath.default_path_specs.inspect}" if DEBUG_TRACE #assert_nil MasterView::DirectiveLoadPath.default_path_specs, 'this is what we'd expect at initial load time' STDOUT.puts "...DirectiveLoadPath.current=#{MasterView::DirectiveLoadPath.current.inspect}" if DEBUG_TRACE #assert_nil MasterView::DirectiveLoadPath.current begin MasterView::DirectiveLoadPath.default_path_specs = path STDOUT.puts "...DirectiveLoadPath.default_path_specs=#{MasterView::DirectiveLoadPath.default_path_specs.object_id}" if DEBUG_TRACE STDOUT.puts "...DirectiveLoadPath.current=#{MasterView::DirectiveLoadPath.current.object_id}" if DEBUG_TRACE STDOUT.puts "...DirectiveLoadPath.default_path_specs=#{MasterView::DirectiveLoadPath.default_path_specs.inspect}" if DEBUG_TRACE assert_not_nil MasterView::DirectiveLoadPath.default_path_specs assert_not_same path, MasterView::DirectiveLoadPath.default_path_specs STDOUT.puts "...DirectiveLoadPath.current=#{MasterView::DirectiveLoadPath.current.inspect}" if DEBUG_TRACE assert_not_nil MasterView::DirectiveLoadPath.current assert_not_same path, MasterView::DirectiveLoadPath.current assert_not_same MasterView::DirectiveLoadPath.current, MasterView::DirectiveLoadPath.default_path_specs ensure # make sure we put the system back into whatever state it was in real_load_path_values.each_pair { | key, real_value | MasterView::DirectiveLoadPath.path_registry[key] = real_value } end end end