require 'test/unit' require 'erb' require 'yaml' require 'socket' require 'rbconfig' require 'tempfile' require 'active_ldap' require File.join(File.expand_path(File.dirname(__FILE__)), "command") LDAP_ENV = "test" unless defined?(LDAP_ENV) module AlTestUtils def self.included(base) base.class_eval do include ActiveLdap::GetTextSupport include Assertions include Config include Connection include Populate include TemporaryEntry include CommandSupport include MockLogger end end module Assertions def assert_true(actual, *args) assert_equal(true, actual, *args) end def assert_false(actual, *args) assert_equal(false, actual, *args) end end module Config def setup super @base_dir = File.expand_path(File.dirname(__FILE__)) @top_dir = File.expand_path(File.join(@base_dir, "..")) @example_dir = File.join(@top_dir, "examples") @config_file = File.join(File.dirname(__FILE__), "config.yaml") ActiveLdap::Base.configurations = read_config end def teardown super end def current_configuration ActiveLdap::Base.configurations[LDAP_ENV] end def read_config unless File.exist?(@config_file) raise "config file for testing doesn't exist: #{@config_file}" end config = YAML.load(ERB.new(File.read(@config_file)).result) _adapter = adapter config.each do |key, value| value[:adapter] = _adapter if _adapter end config end def adapter ENV["ACTIVE_LDAP_TEST_ADAPTER"] end end module ExampleFile def certificate_path File.join(@example_dir, 'example.der') end @@certificate = nil def certificate return @@certificate if @@certificate if File.exists?(certificate_path) @@certificate = File.read(certificate_path) return @@certificate end require 'openssl' rsa = OpenSSL::PKey::RSA.new(512) comment = "Generated by Ruby/OpenSSL" cert = OpenSSL::X509::Certificate.new cert.version = 3 cert.serial = 0 subject = [["OU", "test"], ["CN", Socket.gethostname]] name = OpenSSL::X509::Name.new(subject) cert.subject = name cert.issuer = name cert.not_before = Time.now cert.not_after = Time.now + (365*24*60*60) cert.public_key = rsa.public_key ef = OpenSSL::X509::ExtensionFactory.new(nil, cert) ef.issuer_certificate = cert cert.extensions = [ ef.create_extension("basicConstraints","CA:FALSE"), ef.create_extension("keyUsage", "keyEncipherment"), ef.create_extension("subjectKeyIdentifier", "hash"), ef.create_extension("extendedKeyUsage", "serverAuth"), ef.create_extension("nsComment", comment), ] aki = ef.create_extension("authorityKeyIdentifier", "keyid:always,issuer:always") cert.add_extension(aki) cert.sign(rsa, OpenSSL::Digest::SHA1.new) @@certificate = cert.to_der @@certificate end def jpeg_photo_path File.join(@example_dir, 'example.jpg') end def jpeg_photo File.open(jpeg_photo_path, "rb") {|f| f.read} end end module Connection def setup super ActiveLdap::Base.establish_connection end def teardown ActiveLdap::Base.remove_active_connections! super end end module Populate def setup @dumped_data = nil super begin @dumped_data = ActiveLdap::Base.dump(:scope => :sub) rescue ActiveLdap::ConnectionError end ActiveLdap::Base.delete_all(nil, :scope => :sub) populate end def teardown if @dumped_data ActiveLdap::Base.establish_connection ActiveLdap::Base.delete_all(nil, :scope => :sub) ActiveLdap::Base.load(@dumped_data) end super end def populate populate_base populate_ou populate_user_class populate_group_class populate_associations end def populate_base ActiveLdap::Populate.ensure_base end def ou_class(prefix="") ou_class = Class.new(ActiveLdap::Base) ou_class.ldap_mapping :dn_attribute => "ou", :prefix => prefix, :classes => ["top", "organizationalUnit"] ou_class end def populate_ou %w(Users Groups).each do |name| make_ou(name) end end def make_ou(name) ActiveLdap::Populate.ensure_ou(name) end def populate_user_class @user_class = Class.new(ActiveLdap::Base) @user_class_classes = ["posixAccount", "person"] @user_class.ldap_mapping :dn_attribute => "uid", :prefix => "ou=Users", :scope => :sub, :classes => @user_class_classes end def populate_group_class @group_class = Class.new(ActiveLdap::Base) @group_class.ldap_mapping :prefix => "ou=Groups", :scope => :sub, :classes => ["posixGroup"] end def populate_associations @user_class.belongs_to :groups, :many => "memberUid" @user_class.belongs_to :primary_group, :foreign_key => "gidNumber", :primary_key => "gidNumber" @group_class.has_many :members, :wrap => "memberUid" @group_class.has_many :primary_members, :foreign_key => "gidNumber", :primary_key => "gidNumber" @user_class.set_associated_class(:groups, @group_class) @user_class.set_associated_class(:primary_group, @group_class) @group_class.set_associated_class(:members, @user_class) @group_class.set_associated_class(:primary_members, @user_class) end end module TemporaryEntry include ExampleFile def setup super @user_index = 0 @group_index = 0 end def make_temporary_user(config={}) @user_index += 1 uid = config[:uid] || "temp-user#{@user_index}" ensure_delete_user(uid) do password = config[:password] || "password#{@user_index}" uid_number = config[:uid_number] || default_uid gid_number = config[:gid_number] || default_gid home_directory = config[:home_directory] || "/nonexistent" _wrap_assertion do assert(!@user_class.exists?(uid)) assert_raise(ActiveLdap::EntryNotFound) do @user_class.find(uid).dn end user = @user_class.new(uid) assert(user.new_entry?) user.cn = user.uid user.sn = user.uid user.uid_number = uid_number user.gid_number = gid_number user.home_directory = home_directory user.user_password = ActiveLdap::UserPassword.ssha(password) unless config[:simple] user.add_class('shadowAccount', 'inetOrgPerson', 'organizationalPerson') user.user_certificate = certificate user.jpeg_photo = jpeg_photo end user.save assert(!user.new_entry?) yield(@user_class.find(user.uid), password) end end end def make_temporary_group(config={}) @group_index += 1 cn = config[:cn] || "temp-group#{@group_index}" ensure_delete_group(cn) do gid_number = config[:gid_number] || default_gid _wrap_assertion do assert(!@group_class.exists?(cn)) assert_raise(ActiveLdap::EntryNotFound) do @group_class.find(cn) end group = @group_class.new(cn) assert(group.new_entry?) group.gid_number = gid_number assert(group.save) assert(!group.new_entry?) yield(@group_class.find(group.cn)) end end end def ensure_delete_user(uid) yield(uid) ensure if @user_class.exists?(uid) @user_class.search(:value => uid) do |dn, attribute| @user_class.remove_connection(dn) @user_class.delete(dn) end end end def ensure_delete_group(cn) yield(cn) ensure @group_class.delete(cn) if @group_class.exists?(cn) end def default_uid "10000#{@user_index}" end def default_gid "10000#{@group_index}" end end module CommandSupport def setup super @fakeroot = "fakeroot" @ruby = File.join(::Config::CONFIG["bindir"], ::Config::CONFIG["RUBY_INSTALL_NAME"]) @top_dir = File.expand_path(File.join(File.dirname(__FILE__), "..")) @examples_dir = File.join(@top_dir, "examples") @lib_dir = File.join(@top_dir, "lib") @ruby_args = [ "-I", @examples_dir, "-I", @lib_dir, ] end def run_command(*args, &block) file = Tempfile.new("al-command-support") file.open file.puts(ActiveLdap::Base.configurations["test"].to_yaml) file.close run_ruby(*[@command, "--config", file.path, *args], &block) end def run_ruby(*ruby_args, &block) args = [@ruby, *@ruby_args] args.concat(ruby_args) Command.run(*args, &block) end def run_ruby_with_fakeroot(*ruby_args, &block) args = [@fakeroot, @ruby, *@ruby_args] args.concat(ruby_args) Command.run(*args, &block) end end module MockLogger def make_mock_logger logger = Object.new class << logger def messages(type) @messages ||= {} @messages[type] ||= [] @messages[type] end def info(content=nil) messages(:info) << (block_given? ? yield : content) end def warn(content=nil) messages(:warn) << (block_given? ? yield : content) end def error(content=nil) messages(:error) << (block_given? ? yield : content) end end logger end def with_mock_logger original_logger = ActiveLdap::Base.logger mock_logger = make_mock_logger ActiveLdap::Base.logger = mock_logger yield(mock_logger) ensure ActiveLdap::Base.logger = original_logger end end end