view modules/ssh/spec/classes/init_spec.rb @ 438:bb8f85c35113

Manualy patch SSH module https://github.com/ghoneycutt/puppet-module-ssh/pull/377
author IBBoard <dev@ibboard.co.uk>
date Sun, 14 Aug 2022 11:44:25 +0100
parents d9009f54eb23
children
line wrap: on
line source

require 'spec_helper'

describe 'ssh' do

  default_facts = {
    :fqdn                   => 'monkey.example.com',
    :hostname               => 'monkey',
    :ipaddress              => '127.0.0.1',
    :ipaddress6             => nil,
    :lsbmajdistrelease      => '6',
    :operatingsystemrelease => '6.7',
    :osfamily               => 'RedHat',
    :root_home              => '/root',
    :specific               => 'dummy',
    :ssh_version            => 'OpenSSH_6.6p1',
    :ssh_version_numeric    => '6.6',
    :sshrsakey              => 'AAAAB3NzaC1yc2EAAAABIwAAAQEArGElx46pD6NNnlxVaTbp0ZJMgBKCmbTCT3RaeCk0ZUJtQ8wkcwTtqIXmmiuFsynUT0DFSd8UIodnBOPqitimmooAVAiAi30TtJVzADfPScMiUnBJKZajIBkEMkwUcqsfh630jyBvLPE/kyQcxbEeGtbu1DG3monkeymanOBW1AKc5o+cJLXcInLnbowMG7NXzujT3BRYn/9s5vtT1V9cuZJs4XLRXQ50NluxJI7sVfRPVvQI9EMbTS4AFBXUej3yfgaLSV+nPZC/lmJ2gR4t/tKvMFF9m16f8IcZKK7o0rK7v81G/tREbOT5YhcKLK+0wBfR6RsmHzwy4EddZloyLQ==',
  }

  default_solaris_facts = {
    :fqdn                => 'monkey.example.com',
    :hostname            => 'monkey',
    :ipaddress           => '127.0.0.1',
    :kernelrelease       => '5.10',
    :osfamily            => 'Solaris',
    :root_home           => '/root',
    :specific            => 'dummy',
    :ssh_version         => 'Sun_SSH_2.2',
    :ssh_version_numeric => '2.2',
    :sshrsakey           => 'AAAAB3NzaC1yc2EAAAABIwAAAQEArGElx46pD6NNnlxVaTbp0ZJMgBKCmbTCT3RaeCk0ZUJtQ8wkcwTtqIXmmiuFsynUT0DFSd8UIodnBOPqitimmooAVAiAi30TtJVzADfPScMiUnBJKZajIBkEMkwUcqsfh630jyBvLPE/kyQcxbEeGtbu1DG3monkeymanOBW1AKc5o+cJLXcInLnbowMG7NXzujT3BRYn/9s5vtT1V9cuZJs4XLRXQ50NluxJI7sVfRPVvQI9EMbTS4AFBXUej3yfgaLSV+nPZC/lmJ2gR4t/tKvMFF9m16f8IcZKK7o0rK7v81G/tREbOT5YhcKLK+0wBfR6RsmHzwy4EddZloyLQ==',
  }

  let(:facts) { default_facts }

  osfamily_matrix = {
    'Debian-7' => {
      :architecture           => 'x86_64',
      :osfamily               => 'Debian',
      :operatingsystemrelease => '7',
      :ssh_version            => 'OpenSSH_6.0p1',
      :ssh_version_numeric    => '6.0',
      :ssh_packages           => ['openssh-server', 'openssh-client'],
      :sshd_config_mode       => '0600',
      :sshd_service_name      => 'ssh',
      :sshd_service_hasstatus => true,
      :sshd_config_fixture    => 'sshd_config_debian',
      :ssh_config_fixture     => 'ssh_config_debian',
    },
    'Debian-8' => {
      :architecture           => 'x86_64',
      :osfamily               => 'Debian',
      :operatingsystemrelease => '8',
      :ssh_version            => 'OpenSSH_6.7p1',
      :ssh_version_numeric    => '8.11',
      :ssh_packages           => ['openssh-server', 'openssh-client'],
      :sshd_config_mode       => '0600',
      :sshd_service_name      => 'ssh',
      :sshd_service_hasstatus => true,
      :sshd_config_fixture    => 'sshd_config_debian8',
      :ssh_config_fixture     => 'ssh_config_debian8',
    },
    'Debian-9' => {
      :architecture           => 'x86_64',
      :osfamily               => 'Debian',
      :operatingsystemrelease => '9',
      :ssh_version            => 'OpenSSH_7.4p1',
      :ssh_version_numeric    => '7.4',
      :ssh_packages           => ['openssh-server', 'openssh-client'],
      :sshd_config_mode       => '0600',
      :sshd_service_name      => 'ssh',
      :sshd_service_hasstatus => true,
      :sshd_config_fixture    => 'sshd_config_debian9',
      :ssh_config_fixture     => 'ssh_config_debian9',
    },
    'Debian-10' => {
      :architecture           => 'x86_64',
      :osfamily               => 'Debian',
      :operatingsystemrelease => '10',
      :ssh_version            => 'OpenSSH_7.9p1',
      :ssh_version_numeric    => '7.9',
      :ssh_packages           => ['openssh-server', 'openssh-client'],
      :sshd_config_mode       => '0600',
      :sshd_service_name      => 'ssh',
      :sshd_service_hasstatus => true,
      :sshd_config_fixture    => 'sshd_config_debian10',
      :ssh_config_fixture     => 'ssh_config_debian10',
    },
    'RedHat-5' => {
      :architecture           => 'x86_64',
      :osfamily               => 'RedHat',
      :operatingsystemrelease => '5.11',
      :ssh_version            => 'OpenSSH_4.3p2',
      :ssh_version_numeric    => '4.3',
      :ssh_packages           => ['openssh-server', 'openssh-clients'],
      :sshd_config_mode       => '0600',
      :sshd_service_name      => 'sshd',
      :sshd_service_hasstatus => true,
      :sshd_config_fixture    => 'sshd_config_rhel',
      :ssh_config_fixture     => 'ssh_config_rhel_old',
    },
    'RedHat-6' => {
      :architecture           => 'x86_64',
      :osfamily               => 'RedHat',
      :operatingsystemrelease => '6.7',
      :ssh_version            => 'OpenSSH_5.3p1',
      :ssh_version_numeric    => '5.3',
      :ssh_packages           => ['openssh-server', 'openssh-clients'],
      :sshd_config_mode       => '0600',
      :sshd_service_name      => 'sshd',
      :sshd_service_hasstatus => true,
      :sshd_config_fixture    => 'sshd_config_rhel',
      :ssh_config_fixture     => 'ssh_config_rhel_old',
    },
    'RedHat-7' => {
      :architecture           => 'x86_64',
      :osfamily               => 'RedHat',
      :operatingsystemrelease => '7.2',
      :ssh_version            => 'OpenSSH_6.6p1',
      :ssh_version_numeric    => '6.6',
      :ssh_packages           => ['openssh-server', 'openssh-clients'],
      :sshd_config_mode       => '0600',
      :sshd_service_name      => 'sshd',
      :sshd_service_hasstatus => true,
      :sshd_config_fixture    => 'sshd_config_rhel',
      :ssh_config_fixture     => 'ssh_config_rhel',
    },
    'RedHat-7.4' => {
      :architecture           => 'x86_64',
      :osfamily               => 'RedHat',
      :operatingsystemrelease => '7.4',
      :ssh_version            => 'OpenSSH_6.6p1',
      :ssh_version_numeric    => '6.6',
      :ssh_packages           => ['openssh-server', 'openssh-clients'],
      :sshd_config_mode       => '0600',
      :sshd_service_name      => 'sshd',
      :sshd_service_hasstatus => true,
      :sshd_config_fixture    => 'sshd_config_rhel7',
      :ssh_config_fixture     => 'ssh_config_rhel',
    },
    'Suse-10-x86_64' => {
      :architecture           => 'x86_64',
      :osfamily               => 'Suse',
      :operatingsystem        => 'SLES',
      :operatingsystemrelease => '10.4',
      :ssh_version            => 'OpenSSH_5.1p1',
      :ssh_version_numeric    => '5.1',
      :ssh_packages           => ['openssh'],
      :sshd_config_mode       => '0600',
      :sshd_service_name      => 'sshd',
      :sshd_service_hasstatus => true,
      :sshd_config_fixture    => 'sshd_config_suse_x86_64',
      :ssh_config_fixture     => 'ssh_config_suse_old',
    },
    'Suse-10-i386' => {
      :architecture           => 'i386',
      :osfamily               => 'Suse',
      :operatingsystem        => 'SLES',
      :operatingsystemrelease => '10.4',
      :ssh_version            => 'OpenSSH_5.1p1',
      :ssh_version_numeric    => '5.1',
      :ssh_packages           => ['openssh'],
      :sshd_config_mode       => '0600',
      :sshd_service_name      => 'sshd',
      :sshd_service_hasstatus => true,
      :sshd_config_fixture    => 'sshd_config_suse_i386',
      :ssh_config_fixture     => 'ssh_config_suse_old',
    },
    'Suse-11-x86_64' => {
      :architecture           => 'x86_64',
      :osfamily               => 'Suse',
      :operatingsystem        => 'SLES',
      :operatingsystemrelease => '11.4',
      :ssh_version            => 'OpenSSH_6.6.1p1',
      :ssh_version_numeric    => '6.6',
      :ssh_packages           => ['openssh'],
      :sshd_config_mode       => '0600',
      :sshd_service_name      => 'sshd',
      :sshd_service_hasstatus => true,
      :sshd_config_fixture    => 'sshd_config_suse_x86_64',
      :ssh_config_fixture     => 'ssh_config_suse',
    },
    'Suse-11-i386' => {
      :architecture           => 'i386',
      :osfamily               => 'Suse',
      :operatingsystem        => 'SLES',
      :operatingsystemrelease => '11.4',
      :ssh_version            => 'OpenSSH_6.6.1p1',
      :ssh_version_numeric    => '6.6',
      :ssh_packages           => ['openssh'],
      :sshd_config_mode       => '0600',
      :sshd_service_name      => 'sshd',
      :sshd_service_hasstatus => true,
      :sshd_config_fixture    => 'sshd_config_suse_i386',
      :ssh_config_fixture     => 'ssh_config_suse',
    },
    'Suse-12-x86_64' => {
      :architecture           => 'x86_64',
      :osfamily               => 'Suse',
      :operatingsystem        => 'SLES',
      :operatingsystemrelease => '12.0',
      :ssh_version            => 'OpenSSH_6.6.1p1',
      :ssh_version_numeric    => '6.6',
      :ssh_packages           => ['openssh'],
      :sshd_config_mode       => '0600',
      :sshd_service_name      => 'sshd',
      :sshd_service_hasstatus => true,
      :sshd_config_fixture    => 'sshd_config_sles_12_x86_64',
      :ssh_config_fixture     => 'ssh_config_suse',
    },
    'Solaris-5.11' => {
      :architecture           => 'i86pc',
      :osfamily               => 'Solaris',
      :kernelrelease          => '5.11',
      :ssh_version            => 'Sun_SSH_2.2',
      :ssh_version_numeric    => '2.2',
      :ssh_packages           => ['network/ssh', 'network/ssh/ssh-key', 'service/network/ssh'],
      :sshd_config_mode       => '0644',
      :sshd_service_name      => 'ssh',
      :sshd_service_hasstatus => true,
      :sshd_config_fixture    => 'sshd_config_solaris',
      :ssh_config_fixture     => 'ssh_config_solaris',
    },
    'Solaris-5.10' => {
      :architecture           => 'i86pc',
      :osfamily               => 'Solaris',
      :kernelrelease          => '5.10',
      :ssh_version            => 'Sun_SSH_2.2',
      :ssh_version_numeric    => '2.2',
      :ssh_packages           => ['SUNWsshcu', 'SUNWsshdr', 'SUNWsshdu', 'SUNWsshr', 'SUNWsshu'],
      :sshd_config_mode       => '0644',
      :sshd_service_name      => 'ssh',
      :sshd_service_hasstatus => true,
      :sshd_config_fixture    => 'sshd_config_solaris',
      :ssh_config_fixture     => 'ssh_config_solaris',
    },
    'Solaris-5.9' => {
      :architecture           => 'i86pc',
      :osfamily               => 'Solaris',
      :kernelrelease          => '5.9',
      :ssh_version            => 'Sun_SSH_2.2',
      :ssh_version_numeric    => '2.2',
      :ssh_packages           => ['SUNWsshcu', 'SUNWsshdr', 'SUNWsshdu', 'SUNWsshr', 'SUNWsshu'],
      :sshd_config_mode       => '0644',
      :sshd_service_name      => 'sshd',
      :sshd_service_hasstatus => false,
      :sshd_config_fixture    => 'sshd_config_solaris',
      :ssh_config_fixture     => 'ssh_config_solaris',
    },
    'Ubuntu-1604' => {
      :architecture           => 'x86_64',
      :osfamily               => 'Debian',
      :operatingsystemrelease => '16.04',
      :ssh_version            => 'OpenSSH_7.2p2',
      :ssh_version_numeric    => '7.2',
      :ssh_packages           => ['openssh-server', 'openssh-client'],
      :sshd_config_mode       => '0600',
      :sshd_service_name      => 'ssh',
      :sshd_service_hasstatus => true,
      :sshd_config_fixture    => 'sshd_config_ubuntu1604',
      :ssh_config_fixture     => 'ssh_config_ubuntu1604',
    },
    'Ubuntu-1804' => {
      :architecture           => 'x86_64',
      :osfamily               => 'Debian',
      :operatingsystemrelease => '18.04',
      :ssh_version            => 'OpenSSH_7.6p1',
      :ssh_version_numeric    => '7.6',
      :ssh_packages           => ['openssh-server', 'openssh-client'],
      :sshd_config_mode       => '0600',
      :sshd_service_name      => 'ssh',
      :sshd_service_hasstatus => true,
      :sshd_config_fixture    => 'sshd_config_ubuntu1804',
      :ssh_config_fixture     => 'ssh_config_ubuntu1804',
    },
    'Ubuntu-2004' => {
      :architecture           => 'x86_64',
      :osfamily               => 'Debian',
      :operatingsystemrelease => '20.04',
      :ssh_version            => 'OpenSSH_7.6p1',
      :ssh_version_numeric    => '7.6',
      :ssh_packages           => ['openssh-server', 'openssh-client'],
      :sshd_config_mode       => '0600',
      :sshd_service_name      => 'ssh',
      :sshd_service_hasstatus => true,
      :sshd_config_fixture    => 'sshd_config_ubuntu2004',
      :ssh_config_fixture     => 'ssh_config_ubuntu2004',
    },
    'Ubuntu-2204' => {
      :architecture           => 'x86_64',
      :osfamily               => 'Debian',
      :operatingsystemrelease => '22.04',
      :ssh_version            => 'OpenSSH_8.7p1',
      :ssh_version_numeric    => '8.7',
      :ssh_packages           => ['openssh-server', 'openssh-client'],
      :sshd_config_mode       => '0644',
      :sshd_service_name      => 'ssh',
      :sshd_service_hasstatus => true,
      :sshd_config_fixture    => 'sshd_config_ubuntu2204',
      :ssh_config_fixture     => 'ssh_config_ubuntu2204',
    },
  }

  osfamily_matrix.each do |os, facts|
    context "with default params on osfamily #{os}" do
      let(:facts) { default_facts.merge( facts )}

      it { should compile.with_all_deps }

      it { should contain_class('ssh')}

      it { should_not contain_class('common')}

      facts[:ssh_packages].each do |pkg|
        it {
          should contain_package(pkg).with({
            'ensure' => 'installed',
          })
        }
      end

      it {
        should contain_file('ssh_known_hosts').with({
          'ensure' => 'file',
          'path'   => '/etc/ssh/ssh_known_hosts',
          'owner'  => 'root',
          'group'  => 'root',
          'mode'   => '0644',
        })
      }

      facts[:ssh_packages].each do |pkg|
        it {
          should contain_file('ssh_known_hosts').that_requires("Package[#{pkg}]")
        }
      end

      it {
        should contain_file('ssh_config').with({
          'ensure'  => 'file',
          'path'    => '/etc/ssh/ssh_config',
          'owner'   => 'root',
          'group'   => 'root',
          'mode'    => '0644',
        })
      }

      ssh_config_fixture = File.read(fixtures(facts[:ssh_config_fixture]))
      it { should contain_file('ssh_config').with_content(ssh_config_fixture) }

      facts[:ssh_packages].each do |pkg|
        it {
          should contain_file('ssh_config').that_requires("Package[#{pkg}]")
        }
      end

      it {
        should contain_file('sshd_config').with({
          'ensure'  => 'file',
          'path'    => '/etc/ssh/sshd_config',
          'owner'   => 'root',
          'group'   => 'root',
          'mode'    => facts[:sshd_config_mode],
        })
      }

      facts[:ssh_packages].each do |pkg|
        it {
          should contain_file('sshd_config').that_requires("Package[#{pkg}]")
        }
      end

      sshd_config_fixture = File.read(fixtures(facts[:sshd_config_fixture]))
      it { should contain_file('sshd_config').with_content(sshd_config_fixture) }

      it {
        should contain_service('sshd_service').with({
          'ensure'     => 'running',
          'name'       => facts[:sshd_service_name],
          'enable'     => 'true',
          'hasrestart' => 'true',
          'hasstatus'  => facts[:sshd_service_hasstatus],
          'subscribe'  => 'File[sshd_config]',
        })
      }

      it {
        should contain_resources('sshkey').with({
          'purge' => 'true',
        })
      }

      it { should have_ssh__config_entry_resource_count(0) }

      context 'with exported sshkey resources' do
        subject { exported_resources}
        context 'With only IPv4 address' do
          let(:facts) { default_facts.merge( facts )}
          it { should contain_sshkey('monkey.example.com').with(
            'ensure' => 'present',
            'host_aliases' => ['monkey', '127.0.0.1']
          )}
        end
        context 'With dual stack IP' do
          let(:facts) { default_facts.merge({ :ipaddress6 => 'dead:beef::1/64' }) }
          it { should contain_sshkey('monkey.example.com').with(
            'ensure' => 'present',
            'host_aliases' => ['monkey', '127.0.0.1', 'dead:beef::1/64']
          )}
        end
        context 'With only IPv6 address' do
          let(:facts) { default_facts.merge({ :ipaddress6 => 'dead:beef::1/64', :ipaddress => nil }) }
          it { should contain_sshkey('monkey.example.com').with(
            'ensure' => 'present',
            'host_aliases' => ['monkey', 'dead:beef::1/64']
          )}
        end
      end

    end
  end

  context 'with default params on invalid osfamily' do
    let(:facts) { default_facts.merge({ :osfamily => 'C64' }) }
    let(:params) { { :manage_root_ssh_config => 'invalid' } }

    it 'should fail' do
      expect {
        should contain_class('ssh')
      }.to raise_error(Puppet::Error,/ssh supports osfamilies RedHat, Suse, Debian and Solaris\. Detected osfamily is <C64>\./)
    end
  end

  context 'with optional params used in ssh_config set on valid osfamily' do
    let(:params) do
      {
        :ssh_config_hash_known_hosts        => 'yes',
        :ssh_config_forward_agent           => 'yes',
        :ssh_config_forward_x11             => 'yes',
        :ssh_config_use_roaming             => 'yes',
        :ssh_config_server_alive_interval   => '300',
        :ssh_config_sendenv_xmodifiers      => true,
        :ssh_config_ciphers                 => [ 'aes128-cbc',
                                                 '3des-cbc',
                                                 'blowfish-cbc',
                                                 'cast128-cbc',
                                                 'arcfour',
                                                 'aes192-cbc',
                                                 'aes256-cbc',
        ],
        :ssh_config_kexalgorithms          => [ 'curve25519-sha256@libssh.org',
            'ecdh-sha2-nistp256',
            'ecdh-sha2-nistp384',
            'ecdh-sha2-nistp521',
            'diffie-hellman-group-exchange-sha256',
            'diffie-hellman-group-exchange-sha1',
            'diffie-hellman-group14-sha1',
            'diffie-hellman-group1-sha1',
  ],
        :ssh_config_macs                    => [ 'hmac-md5-etm@openssh.com',
                                                 'hmac-sha1-etm@openssh.com',
        ],
        :ssh_config_proxy_command           => 'ssh -W %h:%p firewall.example.org',
        :ssh_config_global_known_hosts_file => '/etc/ssh/ssh_known_hosts2',
        :ssh_config_global_known_hosts_list => [ '/etc/ssh/ssh_known_hosts3',
                   '/etc/ssh/ssh_known_hosts4',
  ],
        :ssh_config_user_known_hosts_file   => [ '.ssh/known_hosts1',
                                                 '.ssh/known_hosts2',
        ],
        :ssh_hostbasedauthentication        => 'yes',
        :ssh_strict_host_key_checking       => 'ask',
        :ssh_enable_ssh_keysign             => 'yes',
      }
    end

    it { should compile.with_all_deps }

    it {
      should contain_file('ssh_config').with({
        'ensure'  => 'file',
        'path'    => '/etc/ssh/ssh_config',
        'owner'   => 'root',
        'group'   => 'root',
        'mode'    => '0644',
        'require' => ['Package[openssh-server]', 'Package[openssh-clients]'],
      })
    }

    it { should contain_file('ssh_config').with_content(/^# This file is being maintained by Puppet.\n# DO NOT EDIT\n\n# \$OpenBSD: ssh_config,v 1.21 2005\/12\/06 22:38:27 reyk Exp \$/) }
    it { should contain_file('ssh_config').with_content(/^   Protocol 2$/) }
    it { should contain_file('ssh_config').with_content(/^   HashKnownHosts yes$/) }
    it { should contain_file('ssh_config').with_content(/^\s*SendEnv L.*$/) }
    it { should contain_file('ssh_config').with_content(/^  ForwardAgent yes$/) }
    it { should contain_file('ssh_config').with_content(/^  ForwardX11 yes$/) }
    it { should contain_file('ssh_config').with_content(/^\s*GSSAPIAuthentication yes$/) }
    it { should contain_file('ssh_config').with_content(/^\s*UseRoaming yes$/) }
    it { should contain_file('ssh_config').with_content(/^  ServerAliveInterval 300$/) }
    it { should contain_file('ssh_config').with_content(/^  SendEnv XMODIFIERS$/) }
    it { should contain_file('ssh_config').with_content(/^\s*Ciphers aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,arcfour,aes192-cbc,aes256-cbc$/) }
    it { should contain_file('ssh_config').with_content(/^\s*KexAlgorithms curve25519-sha256@libssh.org,ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,diffie-hellman-group-exchange-sha256,diffie-hellman-group-exchange-sha1,diffie-hellman-group14-sha1,diffie-hellman-group1-sha1$/) }
    it { should contain_file('ssh_config').with_content(/^\s*MACs hmac-md5-etm@openssh.com,hmac-sha1-etm@openssh.com$/) }
    it { should contain_file('ssh_config').with_content(/^\s*ProxyCommand ssh -W %h:%p firewall\.example\.org$/) }
    it { should contain_file('ssh_config').with_content(/^\s*GlobalKnownHostsFile \/etc\/ssh\/ssh_known_hosts2 \/etc\/ssh\/ssh_known_hosts3 \/etc\/ssh\/ssh_known_hosts4$/) }
    it { should contain_file('ssh_config').with_content(/^\s*UserKnownHostsFile \.ssh\/known_hosts1 \.ssh\/known_hosts2$/) }
    it { should contain_file('ssh_config').with_content(/^\s*HostbasedAuthentication yes$/) }
    it { should contain_file('ssh_config').with_content(/^\s*StrictHostKeyChecking ask$/) }
    it { should contain_file('ssh_config').with_content(/^\s*EnableSSHKeysign yes$/) }
  end

  context 'with params used in sshd_config set on valid osfamily' do
    let(:params) do
      {
        :sshd_config_port                     => '22222',
        :sshd_config_syslog_facility          => 'DAEMON',
        :sshd_config_login_grace_time         => '60',
        :permit_root_login                    => 'no',
        :sshd_config_chrootdirectory          => '/chrootdir',
        :sshd_config_forcecommand             => '/force/command --with-parameter 242',
        :sshd_config_match                    => { 'User JohnDoe' => [ 'AllowTcpForwarding yes', ], },
        :sshd_config_challenge_resp_auth      => 'no',
        :sshd_config_print_motd               => 'no',
  :sshd_config_print_last_log           => 'no',
        :sshd_config_use_dns                  => 'no',
        :sshd_config_banner                   => '/etc/sshd_banner',
        :sshd_authorized_keys_command         => '/path/to/command',
        :sshd_authorized_keys_command_user    => 'asdf',
        :sshd_banner_content                  => 'textinbanner',
        :sshd_config_xauth_location           => '/opt/ssh/bin/xauth',
        :sshd_config_subsystem_sftp           => '/opt/ssh/bin/sftp',
        :sshd_kerberos_authentication         => 'no',
        :sshd_password_authentication         => 'no',
        :sshd_config_permitemptypasswords     => 'no',
        :sshd_config_permituserenvironment    => 'no',
  :sshd_config_compression              => 'no',
        :sshd_pubkeyacceptedkeytypes          => [ 'ecdsa-sha2-nistp256',
                                                   'ecdsa-sha2-nistp384',
                                                   'ecdsa-sha2-nistp521',
                                                   'ssh-ed25519',
                                                   'ssh-rsa',
        ],
        :sshd_config_authenticationmethods    => [ 'publickey',
                                                   'keyboard-interactive',
        ],
        :sshd_pubkeyauthentication            => 'no',
        :sshd_allow_tcp_forwarding            => 'no',
        :sshd_x11_forwarding                  => 'no',
        :sshd_x11_use_localhost               => 'no',
        :sshd_use_pam                         => 'no',
        :sshd_client_alive_interval           => '242',
        :sshd_config_serverkeybits            => '1024',
        :sshd_client_alive_count_max          => '0',
        :sshd_config_authkey_location         => '.ssh/authorized_keys',
        :sshd_config_hostkey                  => [ '/etc/ssh/ssh_host_rsa_key',
                                                '/etc/ssh/ssh_host_dsa_key',
        ],
        :sshd_config_strictmodes              => 'yes',
        :sshd_config_ciphers                  => [ 'aes128-cbc',
                                                   '3des-cbc',
                                                   'blowfish-cbc',
                                                   'cast128-cbc',
                                                   'arcfour',
                                                   'aes192-cbc',
                                                   'aes256-cbc',
        ],
        :sshd_config_kexalgorithms            => [ 'curve25519-sha256@libssh.org',
               'ecdh-sha2-nistp256',
               'ecdh-sha2-nistp384',
               'ecdh-sha2-nistp521',
               'diffie-hellman-group-exchange-sha256',
               'diffie-hellman-group-exchange-sha1',
               'diffie-hellman-group14-sha1',
               'diffie-hellman-group1-sha1',
  ],
        :sshd_config_macs                     => [ 'hmac-md5-etm@openssh.com',
                                                   'hmac-sha1-etm@openssh.com',
        ],
        :sshd_config_denyusers                => [ 'root',
                                                   'lusers',
        ],
        :sshd_config_denygroups               => [ 'nossh',
                                                   'wheel',
        ],
        :sshd_config_allowusers               => [ 'foo',
                                                   'bar',
        ],
        :sshd_config_allowgroups              => [ 'ssh',
                                                   'security',
        ],
        :sshd_listen_address                  => [ '192.168.1.1',
                                                   '2001:db8::dead:f00d',
        ],
        :sshd_config_tcp_keepalive            => 'yes',
  :sshd_config_use_privilege_separation => 'no',
        :sshd_config_permittunnel             => 'no',
        :sshd_config_allowagentforwarding     => 'no',
        :sshd_config_key_revocation_list      => '/path/to/revocation_list',
      }
    end

    it { should compile.with_all_deps }

    it {
      should contain_file('sshd_config').with({
        'ensure'  => 'file',
        'path'    => '/etc/ssh/sshd_config',
        'owner'   => 'root',
        'group'   => 'root',
        'mode'    => '0600',
        'require' => ['Package[openssh-server]', 'Package[openssh-clients]'],
      })
    }

    it { should contain_file('sshd_config').with_content(/^Port 22222$/) }
    it { should contain_file('sshd_config').with_content(/^SyslogFacility DAEMON$/) }
    it { should contain_file('sshd_config').with_content(/^LogLevel INFO$/) }
    it { should contain_file('sshd_config').with_content(/^LoginGraceTime 60$/) }
    it { should contain_file('sshd_config').with_content(/^PermitRootLogin no$/) }
    it { should contain_file('sshd_config').with_content(/^ChallengeResponseAuthentication no$/) }
    it { should contain_file('sshd_config').with_content(/^PrintMotd no$/) }
    it { should contain_file('sshd_config').with_content(/^PrintLastLog no$/) }
    it { should contain_file('sshd_config').with_content(/^UseDNS no$/) }
    it { should contain_file('sshd_config').with_content(/^Banner \/etc\/sshd_banner$/) }
    it { should contain_file('sshd_config').with_content(/^XAuthLocation \/opt\/ssh\/bin\/xauth$/) }
    it { should contain_file('sshd_config').with_content(/^Subsystem sftp \/opt\/ssh\/bin\/sftp$/) }
    it { should contain_file('sshd_config').with_content(/^PasswordAuthentication no$/) }
    it { should contain_file('sshd_config').with_content(/^KerberosAuthentication no$/) }
    it { should contain_file('sshd_config').with_content(/^AllowTcpForwarding no$/) }
    it { should contain_file('sshd_config').with_content(/^X11Forwarding no$/) }
    it { should contain_file('sshd_config').with_content(/^X11UseLocalhost no$/) }
    it { should contain_file('sshd_config').with_content(/^UsePAM no$/) }
    it { should contain_file('sshd_config').with_content(/^ClientAliveInterval 242$/) }
    it { should contain_file('sshd_config').with_content(/^ServerKeyBits 1024$/) }
    it { should contain_file('sshd_config').with_content(/^ClientAliveCountMax 0$/) }
    it { should contain_file('sshd_config').with_content(/^GSSAPIAuthentication yes$/) }
    it { should contain_file('sshd_config').with_content(/^GSSAPICleanupCredentials yes$/) }
    it { should_not contain_file('sshd_config').with_content(/^\s*PAMAuthenticationViaKBDInt yes$/) }
    it { should_not contain_file('sshd_config').with_content(/^\s*GSSAPIKeyExchange yes$/) }
    it { should contain_file('sshd_config').with_content(/^AcceptEnv L.*$/) }
    it { should contain_file('sshd_config').with_content(/^AuthorizedKeysFile .ssh\/authorized_keys/) }
    it { should contain_file('sshd_config').with_content(/^HostKey \/etc\/ssh\/ssh_host_rsa_key/) }
    it { should contain_file('sshd_config').with_content(/^HostKey \/etc\/ssh\/ssh_host_dsa_key/) }
    it { should contain_file('sshd_config').with_content(/^StrictModes yes$/) }
    it { should contain_file('sshd_config').with_content(/^PermitUserEnvironment no/) }
    it { should contain_file('sshd_config').with_content(/^Compression no$/) }
    it { should contain_file('sshd_config').with_content(/^PermitEmptyPasswords no/) }
    it { should_not contain_file('sshd_config').with_content(/^MaxAuthTries/) }
    it { should_not contain_file('sshd_config').with_content(/^MaxStartups/) }
    it { should_not contain_file('sshd_config').with_content(/^MaxSessions/) }
    it { should contain_file('sshd_config').with_content(/^AuthorizedKeysCommand \/path\/to\/command$/) }
    it { should contain_file('sshd_config').with_content(/^AuthorizedKeysCommandUser asdf$/) }
    it { should contain_file('sshd_config').with_content(/^HostbasedAuthentication no$/) }
    it { should contain_file('sshd_config').with_content(/^PubkeyAcceptedKeyTypes ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,ssh-ed25519,ssh-rsa$/) }
    it { should contain_file('sshd_config').with_content(/^AuthenticationMethods publickey,keyboard-interactive$/) }
    it { should contain_file('sshd_config').with_content(/^PubkeyAuthentication no$/) }
    it { should contain_file('sshd_config').with_content(/^IgnoreUserKnownHosts no$/) }
    it { should contain_file('sshd_config').with_content(/^IgnoreRhosts yes$/) }
    it { should contain_file('sshd_config').with_content(/^ChrootDirectory \/chrootdir$/) }
    it { should contain_file('sshd_config').with_content(/^ForceCommand \/force\/command --with-parameter 242$/) }
    it { should contain_file('sshd_config').with_content(/^Match User JohnDoe\n  AllowTcpForwarding yes\Z/) }
    it { should contain_file('sshd_config').with_content(/^\s*Ciphers aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,arcfour,aes192-cbc,aes256-cbc$/) }
    it { should contain_file('sshd_config').with_content(/^\s*KexAlgorithms curve25519-sha256@libssh.org,ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,diffie-hellman-group-exchange-sha256,diffie-hellman-group-exchange-sha1,diffie-hellman-group14-sha1,diffie-hellman-group1-sha1$/) }
    it { should contain_file('sshd_config').with_content(/^\s*MACs hmac-md5-etm@openssh.com,hmac-sha1-etm@openssh.com$/) }
    it { should contain_file('sshd_config').with_content(/^\s*DenyUsers root lusers$/) }
    it { should contain_file('sshd_config').with_content(/^\s*DenyGroups nossh wheel$/) }
    it { should contain_file('sshd_config').with_content(/^\s*AllowUsers foo bar$/) }
    it { should contain_file('sshd_config').with_content(/^\s*AllowGroups ssh security$/) }
    it { should contain_file('sshd_config').with_content(/^ListenAddress 192.168.1.1\nListenAddress 2001:db8::dead:f00d$/) }
    it { should contain_file('sshd_config').with_content(/^TCPKeepAlive yes$/) }
    it { should contain_file('sshd_config').with_content(/^UsePrivilegeSeparation no$/) }
    it { should contain_file('sshd_config').with_content(/^PermitTunnel no$/) }
    it { should contain_file('sshd_config').with_content(/^RevokedKeys \/path\/to\/revocation_list$/) }

    it {
      should contain_file('sshd_banner').with({
        'ensure'  => 'file',
        'path'    => '/etc/sshd_banner',
        'owner'   => 'root',
        'group'   => 'root',
        'mode'    => '0644',
        'content' => 'textinbanner',
        'require' => ['Package[openssh-server]', 'Package[openssh-clients]'],
      })
    }
  end

  describe 'sshd_config_chrootdirectory param' do
    ['/chrootdir/subdir','/baby/one/more/test',].each do |value|
      context "set to valid #{value} (as #{value.class})" do
        let(:params) { {'sshd_config_chrootdirectory' => value } }

        it { should contain_file('sshd_config').with_content(/^ChrootDirectory #{value}$/) }
      end
    end

    [true,'invalid','invalid/path/',3,2.42,['array'],a = { 'ha' => 'sh' }].each do |value|
      context "set to invalid #{value} (as #{value.class})" do
        let(:params) { {'sshd_config_chrootdirectory' => value } }

        it 'should fail' do
          expect {
            should contain_class('ssh')
          }.to raise_error(Puppet::Error, /is not an absolute path/)
        end
      end
    end

  end

  describe 'sshd_config_forcecommand param' do
    ['/bin/command','/bin/command -parameters','/bin/command --parameters','/bin/command /parameters'].each do |value|
      context "set to valid #{value} (as #{value.class})" do
        let(:params) { {'sshd_config_forcecommand' => value } }

        it { should contain_file('sshd_config').with_content(/^ForceCommand #{value}$/) }
      end
    end

    [true,['array'],a = { 'ha' => 'sh' }].each do |value|
      context "set to invalid #{value} (as #{value.class})" do
        let(:params) { {'sshd_config_forcecommand' => value } }

        it 'should fail' do
          expect {
            should contain_class('ssh')
          }.to raise_error(Puppet::Error, /is not a string/)
        end
      end
    end

  end

  describe 'sshd_config_match param' do
  # match and rules get alphabetically sorted by template, matches should be the last options in sshd_config (regex verify with= \Z)
    context 'set to valid hash containing nested arrays' do
      let(:params) do
        { :sshd_config_match      => {
            'User JohnDoe'        => [ 'AllowTcpForwarding yes', ],
            'Addresss 2.4.2.0'    => [ 'X11Forwarding yes', 'PasswordAuthentication no', ],
          },
        }
      end

      it { should contain_file('sshd_config').with_content(/^Match Addresss 2.4.2.0\n  PasswordAuthentication no\n  X11Forwarding yes\nMatch User JohnDoe\n  AllowTcpForwarding yes\Z/) }
    end

    [true,'string',3,2.42,['array']].each do |value|
      context "set to invalid #{value} (as #{value.class})" do
        let(:params) { {'sshd_config_match' => value } }
        it 'should fail' do
          expect {
            should contain_class('ssh')
          }.to raise_error(Puppet::Error, /is not a Hash/)
        end
      end
    end

  end

describe 'sshd_config_print_last_log param' do
    ['yes','no'].each do |value|
      context "set to #{value}" do
        let (:params) { { :sshd_config_print_last_log => value } }

        it { should contain_file('sshd_config').with_content(/^PrintLastLog #{value}$/) }
      end
    end

    context 'when set to an invalid value' do
      let (:params) { { :sshd_config_print_last_log => 'invalid' } }

      it 'should fail' do
        expect {
          should contain_class('ssh')
        }.to raise_error(Puppet::Error,/ssh::sshd_config_print_last_log may be either \'yes\' or \'no\' and is set to <invalid>\./)
      end
    end
  end

  describe 'sshd_listen_address param' do
    context 'when set to an array' do
      let(:params) { {'sshd_listen_address' => ['192.168.1.1','2001:db8::dead:f00d'] } }

      it { should contain_file('sshd_config').with_content(/^ListenAddress 192.168.1.1\nListenAddress 2001:db8::dead:f00d$/) }
    end

    context 'when set to a string' do
      let(:params) { {'sshd_listen_address' => ['192.168.1.1'] } }

      it { should contain_file('sshd_config').with_content(/^ListenAddress 192.168.1.1$/) }
    end

    context 'when not set' do
      it { should_not contain_file('sshd_config').with_content(/^\s*ListenAddress/) }
    end


    context 'when set to an invalid type (not string or array)' do
      let(:params) { {'sshd_listen_address' => true } }

      it 'should fail' do
        expect {
          should contain_class('ssh')
        }.to raise_error(Puppet::Error)
      end
    end
  end

  describe 'sshd_loglevel param' do
    context 'when set to an invalid value' do
      let(:params) { {'sshd_config_loglevel' => 'BOGON'} }
      it 'should fail' do
        expect {
          should contain_class('ssh')
        }.to raise_error(Puppet::Error, /"BOGON" does not match/)
      end
    end
    ['QUIET', 'FATAL', 'ERROR', 'INFO', 'VERBOSE'].each do |supported_val|
      context "when set to #{supported_val}" do
        let(:params) { { 'sshd_config_loglevel' => supported_val} }
        it { should contain_file('sshd_config').with_content(/^LogLevel #{supported_val}$/) }
      end
    end
  end

  describe 'with sshd_kerberos_authentication' do
    ['yes','no'].each do |value|
      context "set to #{value}" do
        let(:params) { { 'sshd_kerberos_authentication' => value } }

        it { should contain_file('sshd_config').with_content(/^KerberosAuthentication #{value}$/) }
      end
    end

    context 'set to invalid value on valid osfamily' do
      let(:params) { { :sshd_kerberos_authentication => 'invalid' } }

      it 'should fail' do
        expect {
          should contain_class('ssh')
        }.to raise_error(Puppet::Error,/ssh::sshd_kerberos_authentication may be either \'yes\' or \'no\' and is set to <invalid>\./)
      end
    end
  end

  context 'when ssh_config_template has a nonstandard value' do
    context 'and that value is not valid' do
      let(:params) { {'ssh_config_template' => false} }
      it 'should fail' do
        expect {
          should contain_class('ssh')
        }.to raise_error(Puppet::Error, /is not a string/)
      end
    end
    context 'and that value is valid' do
      let(:params) { {'ssh_config_template' => 'ssh/sshd_config.erb'} }
      it 'should lay down the ssh_config file from the specified template' do
        should contain_file('ssh_config').with_content(/OpenBSD: sshd_config/)
      end
    end
  end

  context 'when sshd_config_template has a nonstandard value' do
    context 'and that value is not valid' do
      let(:params) { {'sshd_config_template' => false} }
      it 'should fail' do
        expect {
          should contain_class('ssh')
        }.to raise_error(Puppet::Error, /is not a string/)
      end
    end
    context 'and that value is valid' do
      let(:params) { {'sshd_config_template' => 'ssh/ssh_config.erb'} }
      it 'should lay down the sshd_config file from the specified template' do
        should contain_file('sshd_config').with_content(/OpenBSD: ssh_config/)
      end
    end
  end

  ['true',true].each do |value|
    context "with manage_root_ssh_config set to #{value} on valid osfamily" do
      let(:params) { { :manage_root_ssh_config => value } }

      it { should compile.with_all_deps }

      it { should contain_class('ssh')}

      it { should contain_class('common')}

      it {
        should contain_file('root_ssh_dir').with({
          'ensure'  => 'directory',
          'path'    => '/root/.ssh',
          'owner'   => 'root',
          'group'   => 'root',
          'mode'    => '0700',
          'require' => 'Common::Mkdir_p[/root/.ssh]',
        })
      }

      it {
        should contain_file('root_ssh_config').with({
          'ensure' => 'file',
          'path'   => '/root/.ssh/config',
          'owner'  => 'root',
          'group'  => 'root',
          'mode'   => '0600',
        })
      }
    end
  end

  ['false',false].each do |value|
    context "with manage_root_ssh_config set to #{value} on valid osfamily" do
      let(:params) { { :manage_root_ssh_config => value } }

      it { should compile.with_all_deps }

      it { should contain_class('ssh')}

      it { should_not contain_class('common')}

      it { should_not contain_file('root_ssh_dir') }

      it { should_not contain_file('root_ssh_config') }
    end
  end

  [true,'invalid'].each do |ciphers|
    context "with ssh_config_ciphers set to invalid value #{ciphers}" do
      let(:params) { { :ssh_config_ciphers => ciphers } }

      it 'should fail' do
        expect {
          should contain_class('ssh')
        }.to raise_error(Puppet::Error)
      end
    end
  end

  [true,'invalid'].each do |kexalgorithms|
    context "with ssh_config_kexalgorithms set to invalid value #{kexalgorithms}" do
      let(:params) { { :ssh_config_kexalgorithms => kexalgorithms } }

      it 'should fail' do
        expect {
          should contain_class('ssh')
        }.to raise_error(Puppet::Error)
      end
    end
  end

  [true,'invalid'].each do |macs|
    context "with ssh_config_macs set to invalid value #{macs}" do
      let(:params) { { :ssh_config_macs => macs } }

      it 'should fail' do
        expect {
          should contain_class('ssh')
        }.to raise_error(Puppet::Error)
      end
    end
  end

  [true, ['not','a','string']].each do |proxy_command|
    context "with ssh_config_proxy_command set to invalid value #{proxy_command}" do
      let(:params) { { :ssh_config_proxy_command => proxy_command } }

      it 'should fail' do
        expect {
          should contain_class('ssh')
        }.to raise_error(Puppet::Error)
      end
    end
  end

  describe 'with ssh_config_hash_known_hosts param' do
    ['yes','no','unset'].each do |value|
      context "set to #{value}" do
        let (:params) { { :ssh_config_hash_known_hosts => value } }

        if value == 'unset'
          it { should contain_file('ssh_config').without_content(/^\s*HashKnownHosts/) }
        else
          it { should contain_file('ssh_config').with_content(/^\s*HashKnownHosts #{value}$/) }
        end
      end
    end

    context 'when set to an invalid value' do
      let (:params) { { :ssh_config_hash_known_hosts => 'invalid' } }

      it 'should fail' do
        expect {
          should contain_class('ssh')
        }.to raise_error(Puppet::Error,/ssh::ssh_config_hash_known_hosts may be either \'yes\', \'no\' or \'unset\' and is set to <invalid>\./)
      end
    end
  end

  [true,'invalid'].each do |ciphers|
    context "with sshd_config_ciphers set to invalid value #{ciphers}" do
      let(:params) { { :sshd_config_ciphers => ciphers } }

      it 'should fail' do
        expect {
          should contain_class('ssh')
        }.to raise_error(Puppet::Error)
      end
    end
  end

  [true,'invalid'].each do |kexalgorithms|
    context "with sshd_config_kexalgorithms set to invalid value #{kexalgorithms}" do
      let(:params) { { :sshd_config_kexalgorithms => kexalgorithms } }

      it 'should fail' do
        expect {
          should contain_class('ssh')
        }.to raise_error(Puppet::Error)
      end
    end
  end

  [true,'invalid'].each do |denyusers|
    context "with sshd_config_denyusers set to invalid value #{denyusers}" do
      let(:params) { { :sshd_config_denyusers => denyusers } }

      it 'should fail' do
        expect {
          should contain_class('ssh')
        }.to raise_error(Puppet::Error,/is not an Array/)
      end
    end
  end

  [true,'invalid'].each do |denygroups|
    context "with sshd_config_denygroups set to invalid value #{denygroups}" do
      let(:params) { { :sshd_config_denygroups => denygroups } }

      it 'should fail' do
        expect {
          should contain_class('ssh')
        }.to raise_error(Puppet::Error,/is not an Array/)
      end
    end
  end

  [true,'invalid'].each do |allowusers|
    context "with sshd_config_allowusers set to invalid value #{allowusers}" do
      let(:params) { { :sshd_config_allowusers => allowusers } }

      it 'should fail' do
        expect {
          should contain_class('ssh')
        }.to raise_error(Puppet::Error,/is not an Array/)
      end
    end
  end

  [true,'invalid'].each do |allowgroups|
    context "with sshd_config_allowgroups set to invalid value #{allowgroups}" do
      let(:params) { { :sshd_config_allowgroups => allowgroups } }

      it 'should fail' do
        expect {
          should contain_class('ssh')
        }.to raise_error(Puppet::Error,/is not an Array/)
      end
    end
  end

  [true,'invalid'].each do |macs|
    context "with sshd_config_macs set to invalid value #{macs}" do
      let(:params) { { :sshd_config_macs => macs } }

      it 'should fail' do
        expect {
          should contain_class('ssh')
        }.to raise_error(Puppet::Error)
      end
    end
  end

  describe 'with sshd_config_permitemptypasswords' do
    ['yes','no'].each do |value|
      context "set to #{value}" do
        let(:params) { { 'sshd_config_permitemptypasswords' => value } }

        it { should contain_file('sshd_config').with_content(/^PermitEmptyPasswords #{value}$/) }
      end
    end

    context 'set to invalid value on valid osfamily' do
      let(:params) { { :sshd_config_permitemptypasswords => 'invalid' } }

      it 'should fail' do
        expect {
          should contain_class('ssh')
        }.to raise_error(Puppet::Error,/ssh::sshd_config_permitemptypasswords may be either \'yes\' or \'no\' and is set to <invalid>\./)
      end
    end
  end

  describe 'with sshd_config_permituserenvironment' do
    ['yes','no'].each do |value|
      context "set to #{value}" do
        let(:params) { { 'sshd_config_permituserenvironment' => value } }

        it { should contain_file('sshd_config').with_content(/^PermitUserEnvironment #{value}$/) }
      end
    end

    context 'set to invalid value on valid osfamily' do
      let(:params) { { :sshd_config_permituserenvironment => 'invalid' } }

      it 'should fail' do
        expect {
          should contain_class('ssh')
        }.to raise_error(Puppet::Error,/ssh::sshd_config_permituserenvironment may be either \'yes\' or \'no\' and is set to <invalid>\./)
      end
    end
  end

  describe 'sshd_config_compression param' do
    ['yes','no','delayed'].each do |value|
      context "set to #{value}" do
        let (:params) { { :sshd_config_compression => value } }

        it { should contain_file('sshd_config').with_content(/^Compression #{value}$/) }
      end
    end

    context 'when set to an invalid value' do
      let (:params) { { :sshd_config_compression => 'invalid' } }

      it 'should fail' do
        expect {
          should contain_class('ssh')
        }.to raise_error(Puppet::Error,/ssh::sshd_config_compression may be either \'yes\', \'no\' or \'delayed\' and is set to <invalid>\./)
      end
    end
  end

  describe 'sshd_config_port param' do
    context 'when set to an array' do
      let(:params) { {'sshd_config_port' => ['22222', '22223'] } }

      it { should contain_file('sshd_config').with_content(/^Port 22222\nPort 22223$/) }
    end

    context 'when set to a string' do
      let(:params) { {'sshd_config_port' => '22222' } }

      it { should contain_file('sshd_config').with_content(/^Port 22222$/) }
    end

    context 'when set to an integer' do
      let(:params) { {'sshd_config_port' => 22222 } }

      it { should contain_file('sshd_config').with_content(/^Port 22222$/) }
    end

    context 'when not set to a valid number' do
      let(:params) { {'sshd_config_port' => '22invalid' } }

      it 'should fail' do
        expect {
          should contain_class('ssh')
        }.to raise_error(Puppet::Error,/ssh::sshd_config_port must be a valid number and is set to <22invalid>\./)
      end
    end
  end

  describe 'sshd_config_permittunnel param' do
    ['yes','point-to-point','ethernet','no','unset'].each do |value|
      context "set to #{value}" do
        let (:params) { { :sshd_config_permittunnel => value } }

        if value == 'unset'
          it { should contain_file('sshd_config').without_content(/^\s*PermitTunnel/) }
        else
          it { should contain_file('sshd_config').with_content(/^PermitTunnel #{value}$/) }
        end
      end
    end

    context 'when set to an invalid value' do
      let (:params) { { :sshd_config_permittunnel => 'invalid' } }

      it 'should fail' do
        expect {
          should contain_class('ssh')
        }.to raise_error(Puppet::Error,/ssh::sshd_config_permittunnel may be either \'yes\', \'point-to-point\', \'ethernet\', \'no\' or \'unset\' and is set to <invalid>\./)
      end
    end
  end

  describe 'sshd_config_key_revocation_list param' do
    ['/path/to','unset'].each do |value|
      context "set to #{value}" do
        let (:params) { { :sshd_config_key_revocation_list => value } }

        if value == 'unset'
          it { should contain_file('sshd_config').without_content(/^\s*RevokedKeys/) }
        else
          it { should contain_file('sshd_config').with_content(/^RevokedKeys #{value}$/) }
        end
      end
    end

    context 'when set to an invalid value' do
      let (:params) { { :sshd_config_key_revocation_list => 'invalid' } }

      it 'should fail' do
        expect {
          should contain_class('ssh')
        }.to raise_error(Puppet::Error,/while evaluating a Function Call|is not an absolute path/)
      end
    end
  end

  describe 'sshd_config_hostcertificate param' do
    context 'unset value' do
      let(:params) { { :sshd_config_hostcertificate => 'unset' } }

      it { should contain_file('sshd_config').without_content(/^\s*HostCertificate/) }
    end

    context 'with a certificate' do
      let(:params) { { :sshd_config_hostcertificate => '/etc/ssh/ssh_host_key-cert.pub' } }

      it { should contain_file('sshd_config').with_content(/^HostCertificate \/etc\/ssh\/ssh_host_key-cert\.pub/) }
    end

    context 'with multiple certs' do
      let(:params) { { :sshd_config_hostcertificate => [ '/etc/ssh/ssh_host_key-cert.pub', '/etc/ssh/ssh_host_key-cert2.pub'] } }

      it { should contain_file('sshd_config').with_content(/^HostCertificate \/etc\/ssh\/ssh_host_key-cert\.pub\nHostCertificate \/etc\/ssh\/ssh_host_key-cert2\.pub/)}
    end
  end

  context 'with sshd_config_hostcertificate set to invalid value on valid osfamily' do
    context 'with string' do
      let(:params) { { :sshd_config_hostcertificate => 'invalid' } }

      it 'should fail' do
        expect {
          should contain_class('ssh')
        }.to raise_error(Puppet::Error,/"invalid" is not an absolute path/)
      end
    end
  end

  context 'with sshd_config_authorized_principals_file param' do
    ['unset', '.ssh/authorized_principals'].each do |value|
      context "set to #{value}" do
        let (:params) { { :sshd_config_authorized_principals_file => value } }

        if value == 'unset'
          it { should contain_file('sshd_config').without_content(/^\s*AuthorizedPrincipalsFile/)}
        else
          it { should contain_file('sshd_config').with_content(/^AuthorizedPrincipalsFile \.ssh\/authorized_principals/)}
        end
      end
    end
  end

  describe 'sshd_config_trustedusercakeys param' do
    ['unset', '/etc/ssh/authorized_users_ca.pub', 'none'].each do |value|
      context "set to #{value}" do
        let (:params) { { :sshd_config_trustedusercakeys => value } }

        if value == 'unset'
          it { should contain_file('sshd_config').without_content(/^\s*TrustedUserCAKeys/) }
        else
          it { should contain_file('sshd_config').with_content(/^TrustedUserCAKeys #{value}/) }
        end
      end
    end
  end

  context 'with sshd_config_trustedusercakeys set to invalid value on valid osfamily' do
    let(:params) { { :sshd_config_trustedusercakeys => 'invalid' } }

    it 'should fail' do
      expect {
        should contain_class('ssh')
      }.to raise_error(Puppet::Error,/"invalid" is not an absolute path/)
    end
  end

  context 'with manage_root_ssh_config set to invalid value on valid osfamily' do
    let(:params) { { :manage_root_ssh_config => 'invalid' } }

    it 'should fail' do
      expect {
        should contain_class('ssh')
      }.to raise_error(Puppet::Error,/Unknown type of boolean/)
    end
  end

  context 'with sshd_password_authentication set to invalid value on valid osfamily' do
    let(:params) { { :sshd_password_authentication => 'invalid' } }

    it 'should fail' do
      expect {
        should contain_class('ssh')
      }.to raise_error(Puppet::Error,/ssh::sshd_password_authentication may be either \'yes\' or \'no\' and is set to <invalid>\./)
    end
  end

  context 'with sshd_allow_tcp_forwarding set to invalid value on valid osfamily' do
    let(:params) { { :sshd_allow_tcp_forwarding => 'invalid' } }

    it 'should fail' do
      expect {
        should contain_class('ssh')
      }.to raise_error(Puppet::Error,/ssh::sshd_allow_tcp_forwarding may be either \'yes\' or \'no\' and is set to <invalid>\./)
    end
  end

  context 'with sshd_x11_forwarding set to invalid value on valid osfamily' do
    let(:params) { { :sshd_x11_forwarding => 'invalid' } }

    it 'should fail' do
      expect {
        should contain_class('ssh')
      }.to raise_error(Puppet::Error,/ssh::sshd_x11_forwarding may be either \'yes\' or \'no\' and is set to <invalid>\./)
    end
  end

  context 'with sshd_x11_use_localhost set to invalid value on valid osfamily' do
    let(:params) { { :sshd_x11_use_localhost => 'invalid' } }

    it 'should fail' do
      expect {
        should contain_class('ssh')
      }.to raise_error(Puppet::Error,/ssh::sshd_x11_use_localhost may be either \'yes\' or \'no\' and is set to <invalid>\./)
    end
  end

  context 'with sshd_use_pam set to invalid value on valid osfamily' do
    let(:params) { { :sshd_use_pam => 'invalid' } }

    it 'should fail' do
      expect {
        should contain_class('ssh')
      }.to raise_error(Puppet::Error,/ssh::sshd_use_pam may be either \'yes\' or \'no\' and is set to <invalid>\./)
    end
  end

  context 'with sshd_config_serverkeybits set to invalid value on valid osfamily' do
    let(:params) { { :sshd_config_serverkeybits => 'invalid' } }

    it 'should fail' do
      expect {
        should contain_class('ssh')
      }.to raise_error(Puppet::Error,/ssh::sshd_config_serverkeybits must be an integer and is set to <invalid>\./)
    end
  end

  context 'with sshd_client_alive_interval set to invalid value on valid osfamily' do
    let(:params) { { :sshd_client_alive_interval => 'invalid' } }

    it 'should fail' do
      expect {
        should contain_class('ssh')
      }.to raise_error(Puppet::Error,/ssh::sshd_client_alive_interval must be an integer and is set to <invalid>\./)
    end
  end

  context 'with sshd_client_alive_count_max set to invalid value on valid osfamily' do
    let(:params) { { :sshd_client_alive_count_max => 'invalid' } }

    it 'should fail' do
      expect {
        should contain_class('ssh')
      }.to raise_error(Puppet::Error,/ssh::sshd_client_alive_count_max must be an integer and is set to <invalid>\./)
    end
  end

  context 'with sshd_config_banner set to invalid value on valid osfamily' do
    let(:params) { { :sshd_config_banner => 'invalid/path' } }

    it 'should fail' do
      expect {
        should contain_class('ssh')
      }.to raise_error(Puppet::Error,/is not an absolute path/)
    end
  end

  context 'with sshd_config_authkey_location set to invalid value on valid osfamily' do
    let(:params) { { :sshd_config_authkey_location => false } }

    it 'should fail' do
      expect {
        should contain_class('ssh')
      }.to raise_error(Puppet::Error,/is not a string/)
    end
  end

  context 'with sshd_config_hostkey set to invalid value on valid osfamily' do
    let(:params) { { :sshd_config_hostkey => false } }

    it 'should fail' do
      expect {
        should contain_class('ssh')
      }.to raise_error(Puppet::Error,/is not an Array/)
    end
  end

  context 'with sshd_config_hostkey set to invalid path on valid osfamily' do
    let(:params) { { :sshd_config_hostkey => ['not_a_path'] } }

    it 'should fail' do
      expect {
        should contain_class('ssh')
      }.to raise_error(Puppet::Error,/is not an absolute path./)
    end
  end

  describe 'with sshd_config_allowagentforwarding' do
    ['yes','no'].each do |value|
      context "set to #{value}" do
        let(:params) { { 'sshd_config_allowagentforwarding' => value } }

        it { should contain_file('sshd_config').with_content(/^AllowAgentForwarding #{value}$/) }
      end
    end

    context 'set to invalid value on valid osfamily' do
      let(:params) { { :sshd_config_allowagentforwarding => 'invalid' } }

      it 'should fail' do
        expect {
          should contain_class('ssh')
        }.to raise_error(Puppet::Error,/ssh::sshd_config_allowagentforwarding may be either \'yes\' or \'no\' and is set to <invalid>\./)
      end
    end
  end


  context 'with sshd_config_strictmodes set to invalid value on valid osfamily' do
    let(:params) { { :sshd_config_strictmodes => 'invalid' } }

    it 'should fail' do
      expect {
        should contain_class('ssh')
      }.to raise_error(Puppet::Error,/ssh::sshd_config_strictmodes may be either \'yes\' or \'no\' and is set to <invalid>\./)
    end
  end

  context 'with sshd_authorized_keys_command specified with an invalid path' do
    let(:params) { { :sshd_authorized_keys_command => 'invalid/path' } }

    it 'should fail' do
      expect {
        should contain_class('ssh')
      }.to raise_error(Puppet::Error,/"invalid\/path" is not an absolute path/)
    end
  end

  context 'with sshd_authorized_keys_command_user specified with an invalid type (non-string)' do
    let(:params) { { :sshd_authorized_keys_command_user => ['invalid','type'] } }

    it 'should fail' do
      expect {
        should contain_class('ssh')
      }.to raise_error(Puppet::Error,/\["invalid", "type"\] is not a string/)
    end
  end

  context 'with sshd_banner_content set and with default value on sshd_config_banner on valid osfamily' do
    let(:params) { { :sshd_banner_content => 'textinbanner' } }

    it 'should fail' do
      expect {
        should contain_class('ssh')
      }.to raise_error(Puppet::Error,/ssh::sshd_config_banner must be set to be able to use sshd_banner_content\./)
    end
  end


  context 'with ssh_config_sendenv_xmodifiers set to invalid type, array' do
    let(:params) { { :ssh_config_sendenv_xmodifiers => ['invalid','type'] } }

    it 'should fail' do
      expect {
        should contain_class('ssh')
      }.to raise_error(Puppet::Error,/ssh::ssh_config_sendenv_xmodifiers type must be true or false\./)
    end
  end

  context 'with ssh_config_sendenv_xmodifiers set to stringified \'true\'' do
    let(:params) { { :ssh_config_sendenv_xmodifiers => 'true' } }

    it { should compile.with_all_deps }

    it { should contain_file('ssh_config').with_content(/^  SendEnv XMODIFIERS$/) }
  end

  context 'with manage_firewall set to true on valid osfamily' do
    let(:params) { { :manage_firewall => true } }

    it { should compile.with_all_deps }

    it { should contain_class('ssh')}

    it { should_not contain_class('common')}

    it {
      should contain_firewall('22 open port 22 for SSH').with({
        'action' => 'accept',
        'dport'  => '22',
        'proto'  => 'tcp',
      })
    }
  end

  context 'with config_entries defined on valid osfamily' do
    let(:params) do
      {
        :config_entries => {
          'root' => {
            'owner' => 'root',
            'group' => 'root',
            'path'  => '/root/.ssh/config',
            'host'  => 'test_host1',
          },
          'user' => {
            'owner' => 'user',
            'group' => 'group',
            'path'  => '/home/user/.ssh/config',
            'host'  => 'test_host2',
            'order' => '242',
            'lines' => [ 'ForwardX11 no', 'StrictHostKeyChecking no' ],
          },
        }
      }
    end

    it { should compile.with_all_deps }
    it { should have_ssh__config_entry_resource_count(2) }
    it do
      should contain_ssh__config_entry('root').with({
        'owner' => 'root',
        'group' => 'root',
        'path'  => '/root/.ssh/config',
        'host'  => 'test_host1',
      })
    end
    it do
      should contain_ssh__config_entry('user').with({
        'owner' => 'user',
        'group' => 'group',
        'path'  => '/home/user/.ssh/config',
        'host'  => 'test_host2',
        'order' => '242',
        'lines' => [ 'ForwardX11 no', 'StrictHostKeyChecking no' ],
      })
    end
  end

  describe 'with hiera providing data from multiple levels' do
    let(:facts) do
      default_facts.merge({
        :fqdn     => 'hieramerge.example.com',
        :specific => 'test_hiera_merge',
      })
    end

    context 'with defaults for all parameters' do
      it { should have_ssh__config_entry_resource_count(1) }
      it { should contain_ssh__config_entry('user_from_fqdn') }
    end

    context 'with hiera_merge set to valid <true>' do
      let(:params) { { :hiera_merge => true } }
      it { should have_ssh__config_entry_resource_count(2) }
      it { should contain_ssh__config_entry('user_from_fqdn') }
      it { should contain_ssh__config_entry('user_from_fact') }
    end
  end

  context 'with keys defined on valid osfamily' do
    let(:params) { { :keys => {
      'root_for_userX' => {
        'ensure' => 'present',
        'user'   => 'root',
        'type'   => 'dsa',
        'key'    => 'AAAA==',
      },
      'apache_hup' => {
        'ensure'  => 'present',
        'user'    => 'apachehup',
        'type'    => 'dsa',
        'key'     => 'AAAA==',
        'options' => 'command="/sbin/service httpd restart"',
      },
      'root_for_userY' => {
        'ensure' => 'absent',
        'user'   => 'root',
      }
    } } }

    it { should compile.with_all_deps }

    it {
      should contain_ssh_authorized_key('root_for_userX').with({
        'ensure' => 'present',
        'user'   => 'root',
        'type'   => 'dsa',
        'key'    => 'AAAA==',
      })
    }

    it {
      should contain_ssh_authorized_key('apache_hup').with({
        'ensure'  => 'present',
        'user'    => 'apachehup',
        'type'    => 'dsa',
        'key'     => 'AAAA==',
        'options' => 'command="/sbin/service httpd restart"',
      })
    }

    it {
      should contain_ssh_authorized_key('root_for_userY').with({
        'ensure' => 'absent',
        'user'   => 'root',
      })
    }
  end

  context 'with keys specified as not of type hash' do
    let(:params) { { :keys => [ 'not', 'a', 'hash' ] } }

    it 'should fail' do
      expect {
        should contain_class('ssh')
      }.to raise_error(Puppet::Error)
    end
  end

  describe 'with hiera_merge parameter specified' do
    context 'as a non-boolean or non-string' do
      let(:facts) { default_facts.merge( { :fqdn => 'hieramerge.example.com'} )}
      let(:params) { { :hiera_merge => ['not_a_boolean','or_a_string'] } }

      it 'should fail' do
        expect {
          should contain_class('ssh')
        }.to raise_error(Puppet::Error)
      end
    end

    context 'as an invalid string' do
      let(:params) { { :hiera_merge => 'invalid_string' } }

      it 'should fail' do
        expect {
          should contain_class('ssh')
        }.to raise_error(Puppet::Error,/ssh::hiera_merge may be either 'true' or 'false' and is set to <invalid_string>./)
      end
    end

    ['true',true].each do |value|
      context "as #{value} with hiera data getting collected" do
        let(:facts) { default_facts.merge( { :fqdn => 'hieramerge.example.com'} )}
        let(:params) { { :hiera_merge => value } }

        it { should compile.with_all_deps }

        it { should contain_class('ssh') }

        it { should contain_file('sshd_config').with_content(/^\s*DenyUsers denyuser_from_fqdn/) }
        it { should contain_file('sshd_config').with_content(/^\s*DenyGroups denygroup_from_fqdn/) }
        it { should contain_file('sshd_config').with_content(/^\s*AllowUsers allowuser_from_fqdn/) }
        it { should contain_file('sshd_config').with_content(/^\s*AllowGroups allowgroup_from_fqdn/) }

      end
    end

    context "as true with with hiera data getting merged through levels" do
      let(:facts) do
        default_facts.merge(
          {
            :fqdn              => 'hieramerge.example.com',
            :specific          => 'test_hiera_merge',
          }
        )
      end
      let(:params) { { :hiera_merge => true } }

      it { should compile.with_all_deps }

      it { should contain_class('ssh') }

      it { should contain_file('sshd_config').with_content(/^\s*DenyUsers denyuser_from_fqdn denyuser_from_fact/) }
      it { should contain_file('sshd_config').with_content(/^\s*DenyGroups denygroup_from_fqdn denygroup_from_fact/) }
      it { should contain_file('sshd_config').with_content(/^\s*AllowUsers allowuser_from_fqdn allowuser_from_fact/) }
      it { should contain_file('sshd_config').with_content(/^\s*AllowGroups allowgroup_from_fqdn allowgroup_from_fact/) }

    end

    context "as true with no hiera data provided" do
      let(:facts) do
        default_facts.merge(
          {
            :osfamily               => 'Suse',
            :operatingsystem        => 'SLES',
            :operatingsystemrelease => '11.4',
            :architecture           => 'x86_64',
          }
        )
      end
      let(:params) { { :hiera_merge => true } }

      it { should compile.with_all_deps }

      it { should contain_class('ssh') }

      it { should contain_file('sshd_config').without_content(/^\s*DenyUsers/) }
      it { should contain_file('sshd_config').without_content(/^\s*DenyGroups/) }
      it { should contain_file('sshd_config').without_content(/^\s*AllowUsers/) }
      it { should contain_file('sshd_config').without_content(/^\s*AllowGroups/) }

    end

    ['false',false].each do |value|
      context "as #{value}" do
        let(:params) { { :hiera_merge => value } }

        it { should compile.with_all_deps }

        it { should contain_class('ssh') }
      end
    end
  end

  describe 'with ssh_package_adminfile parameter specified' do
    context 'as a valid path' do
      let(:facts) { default_solaris_facts }
      let(:params) { { :ssh_package_adminfile => '/var/tmp/admin' } }

      ['SUNWsshcu','SUNWsshdr','SUNWsshdu','SUNWsshr','SUNWsshu'].each do |pkg|
        it {
          should contain_package(pkg).with({
            'ensure'    => 'installed',
            'source'    => '/var/spool/pkg',
            'adminfile' => '/var/tmp/admin',
          })
        }
      end
    end

    context 'as an invalid path' do
      let(:facts) { default_solaris_facts }
      let(:params) { { :ssh_package_adminfile => 'invalid/path' } }

      it 'should fail' do
        expect {
          should contain_class('ssh')
        }.to raise_error(Puppet::Error,/is not an absolute path/)
      end
    end
  end

  describe 'with sshd_config_xauth_location parameter specified' do
    context 'as a valid path' do
      let(:params) { { :sshd_config_xauth_location => '/opt/ssh/bin/xauth' } }

      it { should contain_file('sshd_config').with_content(/^XAuthLocation \/opt\/ssh\/bin\/xauth$/) }
    end

    context 'as an invalid path' do
      let(:params) { { :sshd_config_xauth_location => 'invalid/path' } }

      it 'should fail' do
        expect {
          should contain_class('ssh')
        }.to raise_error(Puppet::Error,/is not an absolute path/)
      end
    end

    context 'as an invalid type' do
      let(:params) { { :sshd_config_xauth_location => true } }

      it 'should fail' do
        expect {
          should contain_class('ssh')
        }.to raise_error(Puppet::Error)
      end
    end
  end

  describe 'with ssh_package_source parameter specified' do
    let(:facts) { default_solaris_facts }
    context 'as a valid path' do
      let(:params) { { :ssh_package_source => '/mnt/packages' } }

      ['SUNWsshcu','SUNWsshdr','SUNWsshdu','SUNWsshr','SUNWsshu'].each do |pkg|
        it {
          should contain_package(pkg).with({
            'ensure'    => 'installed',
            'source'    => '/mnt/packages',
            'adminfile' => nil,
          })
        }
      end
    end

    context 'as an invalid path' do
      let(:params) { { :ssh_package_source => 'invalid/path' } }

      it 'should fail' do
        expect {
          should contain_class('ssh')
        }.to raise_error(Puppet::Error,/is not an absolute path/)
      end
    end

    context 'as an invalid type' do
      let(:params) { { :ssh_package_source => true } }

      it 'should fail' do
        expect {
          should contain_class('ssh')
        }.to raise_error(Puppet::Error)
      end
    end
  end

  describe 'with parameter ssh_config_forward_x11_trusted' do
    ['yes','no'].each do |value|
      context "specified as #{value}" do
        let(:params) { { :ssh_config_forward_x11_trusted => value } }

        it { should contain_file('ssh_config').with_content(/^\s*ForwardX11Trusted #{value}$/) }
      end
    end

    context 'not specified' do
      let(:facts) { default_solaris_facts }
      it { should_not contain_file('ssh_config').with_content(/^\s*ForwardX11Trusted/) }
    end

    ['YES',true].each do |value|
      context "specified an invalid value #{value}" do
        let(:params) { { :ssh_config_forward_x11_trusted => value } }

        it 'should fail' do
          expect {
            should contain_class('ssh')
          }.to raise_error(Puppet::Error,/ssh::ssh_config_forward_x11_trusted may be either 'yes' or 'no' and is set to <#{value}>\./)
        end
      end
    end
  end

  describe 'with parameter ssh_gssapidelegatecredentials' do
    ['yes','no'].each do |value|
      context "specified as #{value}" do
        let(:facts) { default_solaris_facts }
        let(:params) { { :ssh_gssapidelegatecredentials => value } }

        it { should contain_file('ssh_config').with_content(/^GSSAPIDelegateCredentials #{value}$/) }
      end
    end

    ['YES',true].each do |value|
      context "specified an invalid value #{value}" do
        let(:params) { { :ssh_gssapidelegatecredentials => value } }

        it 'should fail' do
          expect {
            should contain_class('ssh')
          }.to raise_error(Puppet::Error,/ssh::ssh_gssapidelegatecredentials may be either 'yes' or 'no' and is set to <#{value}>\./)
        end
      end
    end
  end

  describe 'with parameter ssh_gssapiauthentication' do
    ['yes','no'].each do |value|
      context "specified as valid #{value} (as #{value.class})" do
        let(:params) { { :ssh_gssapiauthentication => value } }

        it { should contain_file('ssh_config').with_content(/^\s*GSSAPIAuthentication #{value}$/) }
      end
    end

    ['YES',true,2.42,['array'],a = { 'ha' => 'sh' }].each do |value|
      context "specified as invalid value #{value} (as #{value.class})" do
        let(:params) { { :ssh_gssapiauthentication => value } }

        if value.is_a?(Array)
          value = value.join
        elsif value.is_a?(Hash)
          value = '{ha => sh}'
        end

        it 'should fail' do
          expect {
            should contain_class('ssh')
          }.to raise_error(Puppet::Error,/ssh::ssh_gssapiauthentication may be either 'yes' or 'no' and is set to <#{Regexp.escape(value.to_s)}>\./)
        end
      end
    end
  end

  describe 'with parameter ssh_hostbasedauthentication' do
    ['yes','no'].each do |value|
      context "specified as valid #{value} (as #{value.class})" do
        let(:params) { { :ssh_hostbasedauthentication => value } }

        it { should contain_file('ssh_config').with_content(/^\s*HostbasedAuthentication #{value}$/) }
      end
    end

    ['YES',true,2.42,['array'],a = { 'ha' => 'sh' }].each do |value|
      context "specified as invalid value #{value} (as #{value.class})" do
        let(:params) { { :ssh_hostbasedauthentication => value } }

        if value.is_a?(Array)
          value = value.join
        elsif value.is_a?(Hash)
          value = '{ha => sh}'
        end

        it 'should fail' do
          expect {
            should contain_class('ssh')
          }.to raise_error(Puppet::Error,/ssh::ssh_hostbasedauthentication may be either 'yes' or 'no' and is set to <#{Regexp.escape(value.to_s)}>\./)
        end
      end
    end
  end

  describe 'with parameter ssh_strict_host_key_checking' do
    ['yes','no', 'ask'].each do |value|
      context "specified as valid #{value} (as #{value.class})" do
        let(:params) { { :ssh_strict_host_key_checking => value } }

        it { should contain_file('ssh_config').with_content(/^\s*StrictHostKeyChecking #{value}$/) }
      end
    end

    ['YES',true,2.42,['array'],a = { 'ha' => 'sh' }].each do |value|
      context "specified as invalid value #{value} (as #{value.class})" do
        let(:params) { { :ssh_strict_host_key_checking => value } }

        if value.is_a?(Array)
          value = value.join
        elsif value.is_a?(Hash)
          value = '{ha => sh}'
        end

        it 'should fail' do
          expect {
            should contain_class('ssh')
          }.to raise_error(Puppet::Error,/ssh::ssh_strict_host_key_checking may be 'yes', 'no' or 'ask' and is set to <#{Regexp.escape(value.to_s)}>\./)
        end
      end
    end
  end

  describe 'with parameter ssh_enable_ssh_keysign' do
    ['yes','no'].each do |value|
      context "specified as valid #{value} (as #{value.class})" do
        let(:params) { { :ssh_enable_ssh_keysign => value } }

        it { should contain_file('ssh_config').with_content(/^\s*EnableSSHKeysign #{value}$/) }
      end
    end

    ['YES',true,2.42,['array'],a = { 'ha' => 'sh' }].each do |value|
      context "specified as invalid value #{value} (as #{value.class})" do
        let(:params) { { :ssh_enable_ssh_keysign => value } }

        if value.is_a?(Array)
          value = value.join
        elsif value.is_a?(Hash)
          value = '{ha => sh}'
        end

        it 'should fail' do
          expect {
            should contain_class('ssh')
          }.to raise_error(Puppet::Error,/ssh::ssh_enable_ssh_keysign may be either 'yes' or 'no' and is set to <#{Regexp.escape(value.to_s)}>\./)
        end
      end
    end
  end

  describe 'with parameter sshd_gssapiauthentication' do
    ['yes','no'].each do |value|
      context "specified as valid #{value} (as #{value.class})" do
        let(:params) { { :sshd_gssapiauthentication => value } }

        it { should contain_file('sshd_config').with_content(/^GSSAPIAuthentication #{value}$/) }
      end
    end

    ['YES',true,2.42,['array'],a = { 'ha' => 'sh' }].each do |value|
      context "specified as invalid value #{value} (as #{value.class})" do
        let(:params) { { :sshd_gssapiauthentication => value } }

        if value.is_a?(Array)
          value = value.join
        elsif value.is_a?(Hash)
          value = '{ha => sh}'
        end

        it 'should fail' do
          expect {
            should contain_class('ssh')
          }.to raise_error(Puppet::Error,/ssh::sshd_gssapiauthentication may be either 'yes' or 'no' and is set to <#{Regexp.escape(value.to_s)}>\./)
        end
      end
    end
  end

  describe 'with parameter sshd_gssapikeyexchange' do
    ['yes','no'].each do |value|
      context "specified as #{value}" do
        let(:params) { { :sshd_gssapikeyexchange => value } }

        it { should contain_file('sshd_config').with_content(/^GSSAPIKeyExchange #{value}$/) }
      end
    end

    context 'not specified' do

      it { should_not contain_file('sshd_config').with_content(/^\s*GSSAPIKeyExchange/) }
    end

    ['YES',true].each do |value|
      context "specified an invalid value #{value}" do
        let(:params) { { :sshd_gssapikeyexchange => value } }

        it 'should fail' do
          expect {
            should contain_class('ssh')
          }.to raise_error(Puppet::Error,/ssh::sshd_gssapikeyexchange may be either 'yes' or 'no' and is set to <#{value}>\./)
        end
      end
    end
  end

  describe 'with parameter sshd_pamauthenticationviakbdint' do
    ['yes','no'].each do |value|
      context "specified as #{value}" do
        let(:params) { { :sshd_pamauthenticationviakbdint => value } }

        it { should contain_file('sshd_config').with_content(/^PAMAuthenticationViaKBDInt #{value}$/) }
      end
    end

    context 'not specified' do

      it { should_not contain_file('sshd_config').with_content(/^\s*PAMAuthenticationViaKBDInt/) }
    end

    ['YES',true].each do |value|
      context "specified an invalid value #{value}" do
        let(:params) { { :sshd_pamauthenticationviakbdint => value } }

        it 'should fail' do
          expect {
            should contain_class('ssh')
          }.to raise_error(Puppet::Error,/ssh::sshd_pamauthenticationviakbdint may be either 'yes' or 'no' and is set to <#{value}>\./)
        end
      end
    end
  end

  describe 'with parameter sshd_gssapicleanupcredentials' do
    ['yes','no'].each do |value|
      context "specified as #{value}" do
        let(:params) { { :sshd_gssapicleanupcredentials => value } }

        it { should contain_file('sshd_config').with_content(/^GSSAPICleanupCredentials #{value}$/) }
      end
    end

    context 'not specified' do
      let(:facts) { default_solaris_facts }

      it { should_not contain_file('sshd_config').with_content(/^\s*GSSAPICleanupCredentials/) }
    end

    ['YES',true].each do |value|
      context "specified an invalid value #{value}" do
        let(:params) { { :sshd_gssapicleanupcredentials => value } }

        it 'should fail' do
          expect {
            should contain_class('ssh')
          }.to raise_error(Puppet::Error,/ssh::sshd_gssapicleanupcredentials may be either 'yes' or 'no' and is set to <#{value}>\./)
        end
      end
    end
  end


  describe 'with parameter ssh_sendenv specified' do
    ['true',true].each do |value|
      context "as #{value}" do
        let(:params) { { :ssh_sendenv => value } }

        it { should contain_file('ssh_config').with_content(/^\s*SendEnv/) }
      end
    end

    ['false',false].each do |value|
      context "as #{value}" do
        let(:params) { { :ssh_sendenv => value } }

        it { should_not contain_file('ssh_config').with_content(/^\s*SendEnv/) }
      end
    end

    context 'as an invalid string' do
      let(:params) { { :ssh_sendenv => 'invalid' } }

      it 'should fail' do
        expect {
          should contain_class('ssh')
        }.to raise_error(Puppet::Error,/ssh::ssh_sendenv may be either 'true' or 'false' and is set to <invalid>\./)
      end
    end

    context 'as an invalid type' do
      let(:params) { { :ssh_sendenv => ['invalid','type'] } }

      it 'should fail' do
        expect {
          should contain_class('ssh')
        }.to raise_error(Puppet::Error,/ssh::ssh_sendenv type must be true or false\./)
      end
    end
  end

  describe 'with paramter sshd_config_maxauthtries specified'  do
    context 'as a valid integer' do
     let(:params) { { :sshd_config_maxauthtries => 6}}
     it { should contain_file('sshd_config').with_content(/^MaxAuthTries 6$/)}
    end
    context 'as an invalid type' do
      let(:params) { { :sshd_config_maxauthtries => 'BOGUS'} }
      it 'should fail' do
        expect{
          should contain_class('ssh')
        }.to raise_error(Puppet::Error,/ssh::sshd_config_maxauthtries must be a valid number and is set to <BOGUS>\./)
      end
    end
 end

  describe 'with parameter sshd_config_maxstartups specified' do
    ['10','10:30:100'].each do |value|
      context "as a valid string - #{value}" do
        let(:params) { { :sshd_config_maxstartups => value } }

        it { should contain_file('sshd_config').with_content(/^MaxStartups #{value}$/) }
      end
    end

    ['10a',true,'10:30:1a'].each do |value|
      context "as an invalid string - #{value}" do
        let(:params) { { :sshd_config_maxstartups => value } }

        it 'should fail' do
          expect {
            should contain_class('ssh')
          }.to raise_error(Puppet::Error,/ssh::sshd_config_maxstartups may be either an integer or three integers separated with colons, such as 10:30:100\. Detected value is <#{value}>\./)
        end
      end
    end

    context 'as an invalid type' do
      let(:params) { { :sshd_config_maxstartups => true } }

      it 'should fail' do
        expect {
          should contain_class('ssh')
        }.to raise_error(Puppet::Error)
      end
    end
  end

  describe 'with parameter sshd_config_maxsessions specified' do
    context 'as a valid integer' do
      let(:params) { { :sshd_config_maxsessions => 10 } }

      it { should contain_file('sshd_config').with_content(/^MaxSessions 10$/) }
    end

    context 'as a valid string <unset>' do
      let(:params) { { :sshd_config_maxsessions => 'unset' } }

      it { should contain_file('sshd_config').without_content(/^\s*MaxSessions/) }
    end

    context 'as an invalid type' do
      let(:params) { { :sshd_config_maxsessions => 'BOGUS' } }

      it 'should fail' do
        expect {
          should contain_class('ssh')
        }.to raise_error(Puppet::Error)
      end
    end
  end

  describe 'with parameter sshd_acceptenv specified' do
    ['true',true].each do |value|
      context "as #{value}" do
        let(:params) { { :sshd_acceptenv => value } }

        it { should contain_file('sshd_config').with_content(/^\s*AcceptEnv/) }
      end
    end

    ['false',false].each do |value|
      context "as #{value}" do
        let(:params) { { :sshd_acceptenv => value } }

        it { should_not contain_file('sshd_config').with_content(/^\s*AcceptEnv/) }
      end
    end

    context 'as an invalid string' do
      let(:params) { { :sshd_acceptenv => 'invalid' } }

      it 'should fail' do
        expect {
          should contain_class('ssh')
        }.to raise_error(Puppet::Error,/ssh::sshd_acceptenv may be either 'true' or 'false' and is set to <invalid>\./)
      end
    end

    context 'as an invalid type' do
      let(:params) { { :sshd_acceptenv => ['invalid','type'] } }

      it 'should fail' do
        expect {
          should contain_class('ssh')
        }.to raise_error(Puppet::Error,/ssh::sshd_acceptenv type must be true or false\./)
      end
    end
  end

  describe 'with parameter service_hasstatus' do
    ['true',true,'false',false].each do |value|
      context "specified as #{value}" do
        let(:params) { { :service_hasstatus => value } }

        it {
          should contain_service('sshd_service').with({
            'ensure'     => 'running',
            'name'       => 'sshd',
            'enable'     => 'true',
            'hasrestart' => 'true',
            'hasstatus'  => value,
            'subscribe'  => 'File[sshd_config]',
          })
        }
      end
    end

    context 'specified as an invalid string' do
      let(:params) { { :service_hasstatus => 'invalid' } }

      it 'should fail' do
        expect {
          should contain_class('ssh')
        }.to raise_error(Puppet::Error,/ssh::service_hasstatus must be 'true' or 'false' and is set to <invalid>\./)
      end
    end

    context 'specified as an invalid type' do
      let(:params) { { :service_hasstatus => ['invalid','type'] } }

      it 'should fail' do
        expect {
          should contain_class('ssh')
        }.to raise_error(Puppet::Error,/ssh::service_hasstatus must be true or false\./)
      end
    end
  end

  describe 'with parameter ssh_config_global_known_hosts_file' do
    context 'specified as a valid path' do
      let(:params) { { :ssh_config_global_known_hosts_file => '/valid/path' } }

      it {
        should contain_file('ssh_known_hosts').with({
          'ensure' => 'file',
          'path'   => '/valid/path',
          'owner'  => 'root',
          'group'  => 'root',
          'mode'   => '0644',
          'require' => ['Package[openssh-server]', 'Package[openssh-clients]'],
        })
      }

      it { should contain_file('ssh_config').with_content(/^\s*GlobalKnownHostsFile \/valid\/path$/) }
    end

    context 'specified as an invalid path' do
      let(:params) { { :ssh_config_global_known_hosts_file => 'invalid/path' } }

      it 'should fail' do
        expect {
          should contain_class('ssh')
        }.to raise_error(Puppet::Error,/\"invalid\/path\" is not an absolute path\./)
      end
    end

    context 'specified as an invalid type' do
      let(:params) { { :ssh_config_global_known_hosts_file => { 'invalid' => 'type'} } }

      it 'should fail' do
        expect {
          should contain_class('ssh')
        }.to raise_error(Puppet::Error,/is not an absolute path/)
      end
    end
  end

  describe 'with parameter ssh_config_global_known_hosts_list' do
    context 'when set to an array of valid absolute paths' do
      let(:params) { {'ssh_config_global_known_hosts_list' => ['/valid/path1','/valid/path2'] } }

      it { should contain_file('ssh_config').with_content(/^\s*GlobalKnownHostsFile.*\/valid\/path1 \/valid\/path2$/) }
    end

    context 'specified as an invalid path' do
      let(:params) { { :ssh_config_global_known_hosts_list => ['/valid/path','invalid/path'] } }

      it 'should fail' do
        expect {
          should contain_class('ssh')
        }.to raise_error(Puppet::Error,/\"invalid\/path\" is not an absolute path\./)
      end
    end

    ['YES',true,2.42,a = { 'ha' => 'sh' }].each do |value|
       context "specified as invalid value #{value} (as #{value.class})" do
         let(:params) { { :ssh_config_global_known_hosts_list => value } }

         if value.is_a?(Hash)
           value = '{ha => sh}'
         end

         it 'should fail' do
           expect {
             should contain_class('ssh')
           }.to raise_error(Puppet::Error, /is not an Array/)
         end
       end
     end
  end

  describe 'with parameter ssh_config_user_known_hosts_file' do
    context 'when set to an array of paths' do
      let(:params) { {'ssh_config_user_known_hosts_file' => ['valid/path1','/valid/path2'] } }

      it { should contain_file('ssh_config').with_content(/^\s*UserKnownHostsFile valid\/path1 \/valid\/path2$/) }
    end

    ['YES',true,2.42,a = { 'ha' => 'sh' }].each do |value|
       context "specified as invalid value #{value} (as #{value.class})" do
         let(:params) { { :ssh_config_user_known_hosts_file => value } }

         if value.is_a?(Hash)
           value = '{ha => sh}'
         end

         it 'should fail' do
           expect {
             should contain_class('ssh')
           }.to raise_error(Puppet::Error, /is not an Array/)
         end
       end
     end
  end

  describe 'with parameter ssh_config_global_known_hosts_owner' do
    context 'specified as a valid string' do
      let(:params) { { :ssh_config_global_known_hosts_owner => 'gh' } }

      it {
        should contain_file('ssh_known_hosts').with({
          'ensure' => 'file',
          'path'   => '/etc/ssh/ssh_known_hosts',
          'owner'  => 'gh',
          'group'  => 'root',
          'mode'   => '0644',
          'require' => ['Package[openssh-server]', 'Package[openssh-clients]'],
        })
      }
    end

    context 'specified as an invalid type [non-string]' do
      let(:params) { { :ssh_config_global_known_hosts_owner => ['invalid','type'] } }

      it 'should fail' do
        expect {
          should contain_class('ssh')
        }.to raise_error(Puppet::Error,/\[\"invalid\", \"type\"\] is not a string\.  It looks to be a Array/)
      end
    end
  end

  describe 'with parameter ssh_config_global_known_hosts_group' do
    context 'specified as a valid string' do
      let(:params) { { :ssh_config_global_known_hosts_group => 'gh' } }

      it {
        should contain_file('ssh_known_hosts').with({
          'ensure' => 'file',
          'path'   => '/etc/ssh/ssh_known_hosts',
          'owner'  => 'root',
          'group'  => 'gh',
          'mode'   => '0644',
          'require' => ['Package[openssh-server]', 'Package[openssh-clients]'],
        })
      }
    end

    context 'specified as an invalid type [non-string]' do
      let(:params) { { :ssh_config_global_known_hosts_group => ['invalid','type'] } }

      it 'should fail' do
        expect {
          should contain_class('ssh')
        }.to raise_error(Puppet::Error,/\[\"invalid\", \"type\"\] is not a string\.  It looks to be a Array/)
      end
    end
  end

  describe 'with parameter ssh_config_global_known_hosts_mode' do
    context 'specified as a valid mode' do
      let(:params) { { :ssh_config_global_known_hosts_mode => '0666' } }

      it {
        should contain_file('ssh_known_hosts').with({
          'ensure' => 'file',
          'path'   => '/etc/ssh/ssh_known_hosts',
          'owner'  => 'root',
          'group'  => 'root',
          'mode'   => '0666',
          'require' => ['Package[openssh-server]', 'Package[openssh-clients]'],
        })
      }
    end

    ['666','0842','06666'].each do |value|
      context "specified as invalid mode - #{value}" do
        let(:params) { { :ssh_config_global_known_hosts_mode => value } }

        it 'should fail' do
          expect {
            should contain_class('ssh')
          }.to raise_error(Puppet::Error,/ssh::ssh_config_global_known_hosts_mode must be a valid 4 digit mode in octal notation\. Detected value is <#{value}>\./)
        end
      end
    end

    context 'specified as an invalid type [non-string]' do
      let(:params) { { :ssh_config_global_known_hosts_mode => ['invalid','type'] } }

      it 'should fail' do
        expect {
          should contain_class('ssh')
        }.to raise_error(Puppet::Error,/ssh::ssh_config_global_known_hosts_mode must be a valid 4 digit mode in octal notation\. Detected value is <[\[]?invalid.*type[\]]?/)
      end
    end
  end

  describe 'with ssh_key_import parameter specified' do
    context 'as a non-boolean or non-string' do
    let(:params) { { :ssh_key_import => ['not_a_boolean','or_a_string'] } }

      it 'should fail' do
        expect {
          should contain_class('ssh')
        }.to raise_error(Puppet::Error)
      end
    end

    context 'as an invalid string' do
      let(:params) { { :ssh_key_import => 'invalid_string' } }

      it 'should fail' do
        expect {
          should contain_class('ssh')
        }.to raise_error(Puppet::Error,/ssh::ssh_key_import may be either 'true' or 'false' and is set to <invalid_string>\./)
      end
    end

    ['true',true].each do |value|
      context "as #{value}" do
        let(:params) { { :ssh_key_import => value } }

        it { should compile.with_all_deps }

        it { should contain_class('ssh') }

        it {
          should contain_file('ssh_known_hosts').with({
            'ensure'  => 'file',
            'path'    => '/etc/ssh/ssh_known_hosts',
            'owner'   => 'root',
            'group'   => 'root',
            'mode'    => '0644',
            'require' => ['Package[openssh-server]', 'Package[openssh-clients]'],
          })
        }
      end
    end

    ['false',false].each do |value|
      context "as #{value}" do
        let(:params) { { :ssh_key_import => value } }

        it { should compile.with_all_deps }

        it { should contain_class('ssh') }
      end
    end
  end

  describe 'with parameter sshd_hostbasedauthentication' do
    ['yes','no'].each do |value|
      context "specified as valid #{value} (as #{value.class})" do
        let(:params) { { :sshd_hostbasedauthentication => value } }

        it { should contain_file('sshd_config').with_content(/^HostbasedAuthentication #{value}$/) }
      end
    end

    ['YES',true,2.42,['array'],a = { 'ha' => 'sh' }].each do |value|
      context "specified as invalid value #{value} (as #{value.class})" do
        let(:params) { { :sshd_hostbasedauthentication => value } }

        if value.is_a?(Array)
          value = value.join
        end

        it do
          expect {
            should contain_class('ssh')
          }.to raise_error(Puppet::Error,/ssh::sshd_hostbasedauthentication may be either 'yes' or 'no' and is set to/)
        end
      end
    end
  end

  [true,'invalid'].each do |pubkeyacceptedkeytypes|
    context "with sshd_pubkeyacceptedkeytypes set to invalid value #{pubkeyacceptedkeytypes}" do
      let(:params) { { :sshd_pubkeyacceptedkeytypes => pubkeyacceptedkeytypes } }

      it 'should fail' do
        expect {
          should contain_class('ssh')
        }.to raise_error(Puppet::Error,/is not/)
      end
    end
  end

  [true,'invalid'].each do |authenticationmethods|
    context "with sshd_config_authenticationmethods set to invalid value #{authenticationmethods}" do
      let(:params) { { :sshd_config_authenticationmethods => authenticationmethods } }

      it 'should fail' do
        expect {
          should contain_class('ssh')
        }.to raise_error(Puppet::Error,/is not/)
      end
    end
  end

  describe 'with parameter sshd_pubkeyauthentication' do
    ['yes','no'].each do |value|
      context "specified as valid #{value} (as #{value.class})" do
        let(:params) { { :sshd_pubkeyauthentication => value } }

        it { should contain_file('sshd_config').with_content(/^PubkeyAuthentication #{value}$/) }
      end
    end

    ['YES',true,2.42,['array'],a = { 'ha' => 'sh' }].each do |value|
      context "specified as invalid value #{value} (as #{value.class})" do
        let(:params) { { :sshd_pubkeyauthentication => value } }
        if value.is_a?(Array)
          value = value.join
        end

        it do
          expect {
            should contain_class('ssh')
          }.to raise_error(Puppet::Error,/ssh::sshd_pubkeyauthentication may be either 'yes' or 'no' and is set to/)
        end
      end
    end
  end

  describe 'with parameter sshd_ignoreuserknownhosts' do
    ['yes','no'].each do |value|
      context "specified as valid #{value} (as #{value.class})" do
        let(:params) { { :sshd_ignoreuserknownhosts => value } }

        it { should contain_file('sshd_config').with_content(/^IgnoreUserKnownHosts #{value}$/) }
      end
    end

    ['YES',true,2.42,['array'],a = { 'ha' => 'sh' }].each do |value|
      context "specified as invalid value #{value} (as #{value.class})" do
        let(:params) { { :sshd_ignoreuserknownhosts => value } }
        if value.is_a?(Array)
          value = value.join
        end

        it do
          expect {
            should contain_class('ssh')
          }.to raise_error(Puppet::Error,/ssh::sshd_ignoreuserknownhosts may be either 'yes' or 'no' and is set to/)
        end
      end
    end
  end

  describe 'with parameter sshd_ignorerhosts' do
    ['yes','no'].each do |value|
      context "specified as valid #{value} (as #{value.class})" do
        let(:params) { { :sshd_ignorerhosts => value } }

        it { should contain_file('sshd_config').with_content(/^IgnoreRhosts #{value}$/) }
      end
    end

    ['YES',true,2.42,['array'],a = { 'ha' => 'sh' }].each do |value|
      context "specified as invalid value #{value} (as #{value.class})" do
        let(:params) { { :sshd_ignorerhosts => value } }
        if value.is_a?(Array)
          value = value.join
        end

        it do
          expect {
            should contain_class('ssh')
          }.to raise_error(Puppet::Error,/ssh::sshd_ignorerhosts may be either 'yes' or 'no' and is set to/)
        end
      end
    end
  end

  describe 'with parameter manage_service' do
    ['YES','badvalue',2.42,['array'],a = { 'ha' => 'sh' }].each do |value|
      context "specified as invalid value #{value} (as #{value.class})" do
        let(:params) { { :manage_service => value } }
        it do
          expect {
            should contain_class('ssh')
          }.to raise_error(Puppet::Error,/(is not a boolean|Unknown type of boolean)/)
        end
      end
    end

    ['true', true].each do |value|
      context "specified as valid true value #{value} (as #{value.class})" do
        let(:params) { { :manage_service => value } }
        it { should contain_service('sshd_service') }
      end
    end

    ['false', false].each do |value|
      context "specified as valid false value #{value} (as #{value.class})" do
        let(:params) { { :manage_service => value } }
        it { should_not contain_service('sshd_service') }
      end
    end
  end

  describe 'sshd_config_tcp_keepalive param' do
    ['yes','no','unset'].each do |value|
      context "set to #{value}" do
        let (:params) { { :sshd_config_tcp_keepalive => value } }

        if value == 'unset'
          it { should contain_file('sshd_config').without_content(/^\s*TCPKeepAlive/) }
        else
          it { should contain_file('sshd_config').with_content(/^TCPKeepAlive #{value}$/) }
        end
      end
    end

    context 'when set to an invalid value' do
      let (:params) { { :sshd_config_tcp_keepalive => 'invalid' } }

      it 'should fail' do
        expect {
          should contain_class('ssh')
        }.to raise_error(Puppet::Error,/ssh::sshd_config_tcp_keepalive may be either \'yes\', \'no\' or \'unset\' and is set to <invalid>\./)
      end
    end
  end

  describe 'sshd_config_use_privilege_separation param' do
    ['yes','no','sandbox'].each do |value|
      context "set to #{value}" do
        let (:params) { { :sshd_config_use_privilege_separation => value } }

        it { should contain_file('sshd_config').with_content(/^UsePrivilegeSeparation #{value}$/) }
      end
    end

    context 'when set to an invalid value' do
      let (:params) { { :sshd_config_use_privilege_separation => 'invalid' } }

      it 'should fail' do
        expect {
          should contain_class('ssh')
        }.to raise_error(Puppet::Error,/ssh::sshd_config_use_privilege_separation may be either \'yes\', \'no\' or \'sandbox\' and is set to <invalid>\./)
      end
    end
  end

  describe 'with parameter sshd_addressfamily' do
    ['any','inet','inet6'].each do |value|
      context "set to a valid entry of #{value}" do
        let(:params) { { :sshd_addressfamily => value } }
        it { should contain_file('sshd_config').with_content(/^AddressFamily #{value}$/) }
      end
    end

    ['foo','bar',123].each do |value|
      context "specified as invalid value #{value}" do
        let(:params) { { :sshd_addressfamily => value } }
        it do
          expect {
            should contain_class('ssh')
          }.to raise_error(Puppet::Error,/ssh::sshd_addressfamily can be undef, 'any', 'inet' or 'inet6' and is set to/)
        end
      end
    end
  end

  describe 'with parameter ssh_config_use_roaming' do
    ['yes','no','unset'].each do |value|
      context "set to valid value #{value}" do
        let(:params) { { :ssh_config_use_roaming => value } }
        if value == 'unset'
          it { should contain_file('ssh_config').without_content(/^\s*UseRoaming/) }
        else
          it { should contain_file('ssh_config').with_content(/^\s*UseRoaming #{value}$/) }
        end
      end
    end
  end

  describe 'variable type and content validations' do
    mandatory_params = {} if mandatory_params.nil?

    validations = {
      'hash' => {
        :name    => %w[config_entries],
        :valid   => [], # valid hashes are to complex to block test them here. types::mount should have its own spec tests anyway.
        :invalid => ['string', %w[array], 3, 2.42, true],
        :message => 'is not a Hash',
      },
      'regex (yes|no|unset)' => {
        :name    => %w(ssh_config_use_roaming),
        :valid   => ['yes', 'no', 'unset'],
        :invalid => ['string', %w(array), { 'ha' => 'sh' }, 3, 2.42, true, false, nil],
        :message => 'may be either \'yes\', \'no\' or \'unset\'',
      },
    }

    validations.sort.each do |type, var|
      var[:name].each do |var_name|
        var[:params] = {} if var[:params].nil?
        var[:valid].each do |valid|
          context "when #{var_name} (#{type}) is set to valid #{valid} (as #{valid.class})" do
            let(:params) { [mandatory_params, var[:params], { :"#{var_name}" => valid, }].reduce(:merge) }
            it { should compile }
          end
        end

        var[:invalid].each do |invalid|
          context "when #{var_name} (#{type}) is set to invalid #{invalid} (as #{invalid.class})" do
            let(:params) { [mandatory_params, var[:params], { :"#{var_name}" => invalid, }].reduce(:merge) }
            it { is_expected.to compile.and_raise_error(/#{var[:message]}/) }
          end
        end
      end # var[:name].each
    end # validations.sort.each
  end # describe 'variable type and content validations'

  describe 'sshd_config_include' do
    context 'when set to an array' do
      let(:params) { {'sshd_config_include' => ['file1','file2'] } }

      it { should contain_file('sshd_config').with_content(/^Include file1 file2$/) }
    end

    context 'when set to a string' do
      let(:params) { {'sshd_config_include' => 'file1' } }

      it { should contain_file('sshd_config').with_content(/^Include file1$/) }
    end

    context 'when not set' do
      it { should_not contain_file('sshd_config').with_content(/^\s*Include/) }
    end

    context 'when set to an invalid type (not string or array)' do
      let(:params) { {'sshd_config_include' => true } }

      it 'should fail' do
        expect {
          should contain_class('ssh')
        }.to raise_error(Puppet::Error)
      end
    end
  end

  describe 'ssh_config_include' do
    context 'when set to an array' do
      let(:params) { {'ssh_config_include' => ['file1','file2'] } }

      it { should contain_file('ssh_config').with_content(/^Include file1 file2$/) }
    end

    context 'when set to a string' do
      let(:params) { {'ssh_config_include' => 'file1' } }

      it { should contain_file('ssh_config').with_content(/^Include file1$/) }
    end

    context 'when not set' do
      it { should_not contain_file('ssh_config').with_content(/^\s*Include/) }
    end

    context 'when set to an invalid type (not string or array)' do
      let(:params) { {'ssh_config_include' => true } }

      it 'should fail' do
        expect {
          should contain_class('ssh')
        }.to raise_error(Puppet::Error)
      end
    end
  end

end