pax_global_header00006660000000000000000000000064131261457560014524gustar00rootroot0000000000000052 comment=a5cdfdc81ec93af2c4d77d45a3c892c40c2826f5 rspec-puppet-2.6.1/000077500000000000000000000000001312614575600141615ustar00rootroot00000000000000rspec-puppet-2.6.1/.gitignore000066400000000000000000000001041312614575600161440ustar00rootroot00000000000000*.gem /Gemfile.lock /Gemfile.local /.bundle/ /vendor/ .ruby-version rspec-puppet-2.6.1/.rspec000066400000000000000000000000371312614575600152760ustar00rootroot00000000000000--color --format documentation rspec-puppet-2.6.1/.travis.yml000066400000000000000000000024411312614575600162730ustar00rootroot00000000000000language: ruby cache: bundler bundler_args: --without development rvm: - 2.3.0 - 2.1 - 1.9.3 sudo: false env: - PUPPET_GEM_VERSION='~> 4.8.0' COVERAGE=yes - PUPPET_GEM_VERSION='~> 4.7.0' - PUPPET_GEM_VERSION='~> 4.5.0' - PUPPET_GEM_VERSION='~> 4.4.0' - PUPPET_GEM_VERSION='~> 4.3.0' - PUPPET_GEM_VERSION='~> 4.2.0' # Latest gem release - PUPPET_GEM_VERSION='~> 4.0' # Latest code from puppetlabs/puppet.git - PUPPET_GEM_VERSION='https://github.com/puppetlabs/puppet.git#master' - PUPPET_GEM_VERSION='https://github.com/puppetlabs/puppet.git#stable' matrix: include: # these versions are explicitly needed for ruby 1.8.7 support - rvm: 1.8.7 env: PUPPET_GEM_VERSION='~> 3.8.0' RSPEC_GEM_VERSION='= 3.1.0' - rvm: 1.8.7 env: PUPPET_GEM_VERSION='~> 2.7.0' RSPEC_GEM_VERSION='~> 2.14.0' exclude: - rvm: 2.1 env: PUPPET_GEM_VERSION='~> 4.1.0' # run Coveralls exactly once - rvm: 1.9.3 env: PUPPET_GEM_VERSION='~> 4.8.0' COVERAGE=yes - rvm: 2.3.0 env: PUPPET_GEM_VERSION='~> 4.8.0' COVERAGE=yes allowed_failures: # Don't fail for puppet.git#master because it may be to blame for any failures - env: PUPPET_GEM_VERSION='https://github.com/puppetlabs/puppet.git#master' notifications: email: - tim@github.com rspec-puppet-2.6.1/CHANGELOG.md000066400000000000000000000261221312614575600157750ustar00rootroot00000000000000# Change Log All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). ## [2.6.1] ### Fixed * 2.6.0 introduced a change to how resource titles are rendered in the test manifest which caused them to get rendered as double quoted strings. This caused a failure for tests of defined types that contained `$` characters as Puppet would try and interpolate the values in the title as variable(s). ## [2.6.0] The Windows parity release. rspec-puppet now officially supports Windows. A lot of work has been put in to support cross-platform tests, so that you can now test your Windows manifests on \*nix, and your \*nix manifests on Windows. ### Changed * Puppet settings are now applied as application overrides, allowing users to call `Puppet.settings` directly to make changes to settings without them getting clobbered by rspec-puppet. * Improved support for setting up the `spec/fixtures/modules` link on Windows by using directory junctions instead of symlinks, removing the need for Administrator access. * When testing for the absence of a parameter on a resource, the error message now contains the value(s) of the parameter(s) that should be undefined. * When testing a defined type, the defined type being tested is no longer part of the coverage report. * The cached catalogue will now be invalidated when hiera-puppet-helper users change their `hiera_data` value. * Multiple instances of a defined type can now be tested at once by providing an array of strings with `let(:title)`. * Explicitly specifying the type of an example group (`:type => :class`) now takes precedence over the type inferred from the spec file's location. * The manifest specified in `RSpec.configuration.manifest` (path to `site.pp` for Puppet < 4.x) is now imported if specified on Puppet >= 4.x. * Puppet functions called when testing a Puppet function now get executed in the same scope as parent function. ### Added * The module is now automatically linked into `spec/fixtures/modules` at the start of the rspec-puppet run. * CI testing of PRs on Windows via Appveyor. * Support for setting node parameters (mocking the behaviour of an ENC or Puppet Enterprise Console) using `let(:node_params)`. * Support for injecting Puppet code at the end of the test code using `let(:post_condition)`. * Resource coverage reports for `host` specs. * Puppet functions that take a lambda as a parameter can now be tested by chaining `with_lambda` to the `run` matcher. * Facts and trusted facts are now available when testing Puppet functions. * Hiera configuration can now be specified when testing Puppet functions using `let(:hiera_config)`. * Trusted facts (`$trusted[]`) can now be specified in `RSpec.configuration.default_trusted_facts` or by `let(:trusted_facts)`. * `:default` is now a supported parameter value when passed in by `let(:params)`. * Support for testing Puppet data type aliases. ### Fixed * Facts generated from the node name (as set by `let(:node)`) now take precedence over the values specified in `RSpec.configuration.default_facts` or by `let(:facts)`. * Only fact names will now be converted to lowercase, not the fact values. * Matchers now support resources where the namevar has a different value to the title. * Resources created outside of the module being tested by functions like `create_resources` or `ensure_package` are no longer present in the coverage report from Puppet 4.6 onwards. * Guards have been put in place to prevent the possibility of rspec-puppet getting stuck in an infinite recursion when testing the relationships between resources. * A full `spec/spec_helper.rb` file is now written out by `rspec-puppet-init` to fix the `fixture_path` issue on new modules. * The namevar of a resources is no longer taken into account when testing the exact parameters of the resource with `only_with`. * Minimum resource coverage check for RSpec <= 3.2. * Resource parameters that take a hash as their value will no longer have that hash converted into an array. * Testing the value of a parameter with a Proc that returns `nil` now works as expected. * When testing Puppet functions, the function name is no longer automatically coverted to lowercase. * The value of `$::environment` is now forced to be a string as expected for Puppet 4.0 - 4.3. * app\_management is no longer enabled by rspec-puppet for Puppet >= 5.0 as it is already enabled by default. * Failing to provide parameters when testing an application now raises the correct exception (`ArgumentError`). * Ruby symbols in nested hashes or arrays are now converted into strings when passed in by `let(:params)`. * Namespaced resources are now correctly capitalised when being added to the resource coverage filter. ## [2.5.0] Headline features are app management, nested hashes in params, and testing for "internal" functions. Thanks to everyone who contributed: Leo Arnold, Matt Schuchard, and Si Wilkins ### Changed * Updates to the README * Improve Gemfile to work with older rubies ### Added * Add support for app management testing * Enable nested hashes in params * After refactoring the function test code, puppet 4 "internal" functions can now be tested too * Link functions and types on setup * Increased test coverage ## [2.4.0] This release now supports testing exported resources in the same way that normal resources in the catalog are tested. Access them in your examples using `exported_resources`. See "Testing Exported Resources" in the README for examples. ### Changed * This release pulls out much of the version-specific code into separate classes to reduce complexity and enable easier maintenance going forward. ### Added * Support colon-separated module_path and environmentpath values. * Support a threshold for the code coverage test, that can fail the whole run. * Ensure a consistent environment for all examples by adding a forced initialization of puppet before each. ### Credits Thanks to Adrien Thebo, Arthur Gautier, Brett Gray, and Nicholas Hinds, as well as all the folks helping out on github for their contributions to this release. ## [2.3.2] Properly fix yesterday's issue by unsharing the cache key before passing the data to puppet. This also contains a new test matrix to avoid missing a half-baked fix like yesterday. ## [2.3.1] A quick workaround to re-enable testing with the recently released puppet 3.8.5 and the soon to be released puppet 4.3.2. See PUP-5743 for the gritty details. Upgrade to this version if you hit the "undefined method \`resource' for nil:NilClass" error. ## [2.3.0] Rspec-puppet now supports testing custom types, `:undef` values in params, structured facts, and checks resource dependencies recursively. The settings in `module_path` and `manifest` are now respected throughout the code base. The former default for `module_path` (`'/etc/puppet/modules'`) was dropped to avoid accidentally poisoning the test environment with unrelated code. To reduce the maintenance overhead of boilerplate code, rspec-puppet now provides some of the code that rspec-puppet-init deployed in helper files that you can just `require` instead. This release also reduces memory usage on bigger testsuites drastically by reducing the caching of compiled catalogs. ### Changed - Limit the catalogue cache to 16 entries. Significant memory savings and reduced runtime were observed in testing this. - Prevent Puppet 3's \_timestamp fact from invalidating cache. - Extracted catalog cache from RSpec::Puppet::Support. - Updated README to use the rspec 3 syntax, and additional explanations. - `contain_file(...).with_content(...)` will now only show the diff and not the full contents of the file. ### Added - Custom type testing example group and matcher. - before/require/subscribe/notify checking now searches recursively through all dependencies. `File[a] -> File[b] -> File[c]` is now matched by `contain_file('a').that_comes_before('File[c]')`, whereas earlier versions would have missed that. - `let(:params)` now allows `:undef` to pass a literal undef value through to the subject. - Support structured facts with keys as symbols or strings (\#295). - rspec-puppet-init now creates smaller files, using rspec-puppet helpers, instead of pasting code into the module. - Added a list of related projects to the README. ### Fixed - Fix #276: `compile.and_raise_error` now correctly considers successful compilation an error - Puppet's `modulepath` can now contain multiple entries and rspec-puppet will configure puppet to load code from all of them - Support running with rspec 2.99 again - non-class resources are now covered by the coverage code - Fix #323/MODULES-2374: autorequires checking doesn't abort on "undefined method \`[]' for nil:NilClass" - improved documentation for hiera integration, added example spec - document the `scope` property ### Credits Thanks to Adrien Thebo, Alex Harvey, Brian, Dan Bode, Dominic Cleal, Javier Palacios, Jeff McCune, Jordan Moldow, Peter van Zetten, Raphaël Pinson, Simon Kohlmeyer, and Tristan Colgate for their contributions to this release. -- David Schmitt ## [2.2.0] ### Added - Settings for ordering, strict_variables, stringify_facts, and trusted_node_data - Expose the scope in function example groups ### Fixed - rspec-puppet-init now works with Puppet 4 - Several fixes and enhancements for the `run` matcher - Recompile the catalog when the hiera config changes ## [2.1.0] - 2015-04-21 ### Added - Puppet 4 support - Ability to set `environment` in a let block - Better function failure messages ### Fixed - Filter fixtures from coverage reports - Fix functions accidentally modifying rspec function arguments - Restructured TravisCI matrix (NB: Puppet 2.6 is no longer tested) ## [2.0.1] - 2015-03-12 ### Fixed - Allow RSpec 2 to still be used ## [2.0.0] - 2014-12-02 ### Changed - `subject` is now a lambda to enable catching compilation failures. ### Added - Ability to use RSpec 3 - Hiera integration - Coverage reports - Ability to test on the future parser - Function tests now have a catalogue - Add array of references support to Relationship matchers `that_requires`, `that_comes_before`, `that_notifies`, and `that_subscribes_to` ### Fixed - Better error messaging and handling for parameters (`nil` and friends) and dependency cycles ## 1.0.1 and earlier For changelog of versions 1.0.1 and earlier, see http://rspec-puppet.com/changelog/ [2.x]: https://github.com/rodjek/rspec-puppet/compare/v2.5.0...master [2.5.0]: https://github.com/rodjek/rspec-puppet/compare/v2.4.0...v2.5.0 [2.4.0]: https://github.com/rodjek/rspec-puppet/compare/v2.3.2...v2.4.0 [2.3.2]: https://github.com/rodjek/rspec-puppet/compare/v2.3.1...v2.3.2 [2.3.1]: https://github.com/rodjek/rspec-puppet/compare/v2.3.0...v2.3.1 [2.3.0]: https://github.com/rodjek/rspec-puppet/compare/v2.2.0...v2.3.0 [2.2.0]: https://github.com/rodjek/rspec-puppet/compare/v2.1.0...v2.2.0 [2.1.0]: https://github.com/rodjek/rspec-puppet/compare/v2.0.1...v2.1.0 [2.0.1]: https://github.com/rodjek/rspec-puppet/compare/v2.0.0...v2.0.1 [2.0.0]: https://github.com/rodjek/rspec-puppet/compare/v1.0.1...v2.0.0 rspec-puppet-2.6.1/Gemfile000066400000000000000000000026451312614575600154630ustar00rootroot00000000000000source ENV['GEM_SOURCE'] || "https://rubygems.org" def location_for(place, fake_version = nil) if place =~ /^((?:git|https?)[:@][^#]*)#(.*)/ [fake_version, { :git => $1, :branch => $2, :require => false }].compact elsif place =~ /^file:\/\/(.*)/ ['>= 0', { :path => File.expand_path($1), :require => false }] else [place, { :require => false }] end end gemspec # ffi (specifically the x64-mingw32 variant) requires ruby >= 2.0 after version 1.9.14 if RUBY_VERSION =~ /^1\.?9/ gem 'ffi', '<= 1.9.14' end gem 'rspec', *location_for(ENV['RSPEC_GEM_VERSION'] || '~> 3.0') gem 'puppet', *location_for(ENV['PUPPET_GEM_VERSION'] || '~> 4.0') gem 'pry', :group => :development if RUBY_VERSION =~ /^1\.?/ gem 'rake', '10.5.0' # still supports 1.8 else gem 'rake' end # json_pure 2.0.2 added a requirement on ruby >= 2. We pin to json_pure 2.0.1 # if using ruby 1.9; older ruby versions do not support puppets that require # these gems. if RUBY_VERSION =~ /^1\.?9/ gem 'json_pure', '<=2.0.1' # rubocop 0.42.0 requires ruby >=2; 1.8 is not supported gem 'rubocop', '0.41.2' if RUBY_VERSION =~ /^1\.?9/ elsif RUBY_VERSION =~ /^1\.?8/ gem 'json_pure', '< 2.0.0' else gem 'rubocop' gem 'rubocop-rspec', '~> 1.6' if (RUBY_VERSION >= '2.3.0' || RUBY_VERSION >= '23') end if ENV['COVERAGE'] == 'yes' gem 'coveralls', :require => false end if File.exist?('Gemfile.local') eval_gemfile('Gemfile.local') end rspec-puppet-2.6.1/LICENSE000066400000000000000000000020361312614575600151670ustar00rootroot00000000000000Copyright (c) 2011 Tim Sharpe Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. rspec-puppet-2.6.1/README.md000066400000000000000000000723511312614575600154500ustar00rootroot00000000000000# RSpec tests for your Puppet manifests & modules [![Build Status](https://travis-ci.org/rodjek/rspec-puppet.svg?branch=master)](https://travis-ci.org/rodjek/rspec-puppet) [![Coverage Status](https://coveralls.io/repos/rodjek/rspec-puppet/badge.svg?branch=master)](https://coveralls.io/r/rodjek/rspec-puppet?branch=master) ## Installation gem install rspec-puppet > Note for ruby 1.8 users: while rspec-puppet itself supports ruby 1.8, you'll > need to pin rspec itself to `~> 3.1.0`, as later rspec versions do not work > on old rubies anymore. ## Starting out with a new module When you start out on a new module, run `rspec-puppet-init` to create the necessary files to configure rspec-puppet for your module's tests. ## Configure manifests for Puppet 4 With Puppet 3, the manifest is set to `$manifestdir/site.pp`. However Puppet 4 defaults to an empty value. In order to test manifests you will need to set appropriate settings. Puppet configuration reference for `manifest` can be found online: * Puppet 3: https://docs.puppet.com/puppet/3.8/reference/configuration.html#manifest * Puppet 4: https://docs.puppet.com/puppet/4.8/reference/configuration.html#manifest Configuration is typically done in a `spec/spec_helper.rb` file which each of your spec will require. Example code: ```ruby # /spec base_dir = File.dirname(File.expand_path(__FILE__)) RSpec.configure do |c| c.module_path = File.join(base_dir, 'fixtures', 'modules') c.manifest_dir = File.join(base_dir, 'fixtures', 'manifests') c.manifest = File.join(base_dir, 'fixtures', 'manifests', 'site.pp') c.environmentpath = File.join(Dir.pwd, 'spec') # Coverage generation c.after(:suite) do RSpec::Puppet::Coverage.report! end end ``` ## Configuration rspec-puppet can be configured by modifying the `RSpec.configure` block in your `spec/spec_helper.rb` file. ``` RSpec.configure do |c| c. = end ``` #### manifest\_dir Type | Default | Puppet Version(s) ------ | -------- | ----------------- String | Required | 2.x, 3.x The path to the directory containing your basic manifests like `site.pp`. #### module\_path Type | Default | Puppet Version(s) ------ | -------- | ----------------- String | Required | 2.x, 3.x, 4.x The path to the directory containing your Puppet modules. #### default\_facts Type | Default | Puppet Version(s) ---- | ------- | ----------------- Hash | `{}` | 2.x, 3.x, 4.x A hash of default facts that should be used for all the tests. #### hiera\_config Type | Default | Puppet Version(s) ------ | ------------- | ----------------- String | `"/dev/null"` | 3.x, 4.x The path to your `hiera.yaml` file (if used). #### default\_node\_params Type | Default | Puppet Version(s) ---- | ------- | ----------------- Hash | `{}` | 4.x A hash of default node parameters that should be used for all the tests. #### default\_trusted\_facts Type | Default | Puppet Version(s) ---- | ------- | ----------------- Hash | `{}` | 4.x A hash of default trusted facts that should be used for all the tests (available in the manifests as the `$trusted` hash). In order to use this, the `trusted_node_data` setting must be set to `true`. #### trusted\_node\_data Type | Default | Puppet Version(s) ------- | ------- | ----------------- Boolean | `false` | 3.x, 4.x Configures rspec-puppet to use the `$trusted` hash when compiling the catalogues. #### confdir Type | Default | Puppet Version(s) ------ | --------------- | ----------------- String | `"/etc/puppet"` | 2.x, 3.x, 4.x The path to the main Puppet configuration directory. #### config Type | Default | Puppet Version(s) ------ | ---------------------- | ----------------- String | Puppet's default value | 2.x, 3.x, 4.x The path to `puppet.conf`. #### manifest Type | Default | Puppet Version(s) ------ | ---------------------- | ----------------- String | Puppet's default value | 2.x, 3.x The entry-point manifest for Puppet, usually `$manifest_dir/site.pp`. #### template\_dir Type | Default | Puppet Version(s) ------ | ------- | ----------------- String | `nil` | 2.x, 3.x The path to the directory that Puppet should search for templates that are stored outside of modules. #### environmentpath Type | Default | Puppet Version(s) ------ | ------------------------------------- | ----------------- String | `"/etc/puppetlabs/code/environments"` | 4.x The search path for environment directories. #### parser Type | Default | Puppet Version(s) ------ | ----------- | ----------------- String | `"current"` | 3.x This switches between the 3.x (`current`) and 4.x (`future`) parsers. #### ordering Type | Default | Puppet Version(s) ------ | -------------- | ----------------- String | `"title-hash"` | 3.x, 4.x How unrelated resources should be ordered when applying a catalogue. * `manifest` - Use the order in which the resources are declared in the manifest. * `title-hash` - Order the resources randomly, but in a consistent manner across runs (the order will only change if the manifest changes). * `random` - Order the resources randomly. #### strict\_variables Type | Default | Puppet Version(s) ------- | ------- | ----------------- Boolean | `false` | 3.x, 4.x Makes Puppet raise an error when it tries to reference a variable that hasn't been defined (not including variables that have been explicitly set to `undef`). #### stringify\_facts Type | Default | Puppet Version(s) ------- | ------- | ----------------- Boolean | `true` | 3.x, 4.x Makes rspec-puppet coerce all the fact values into strings (matching the behaviour of older versions of Puppet). #### enable\_pathname\_stubbing Type | Default | Puppet Version(s) ------- | ------- | ----------------- Boolean |`false` | 2.x, 3.x, 4.x Configures rspec-puppet to stub out `Pathname#absolute?` with it's own implementation. This should only be enabled if you're running into an issue running cross-platform tests where you have Ruby code (types, providers, functions, etc) that use `Pathname#absolute?`. ## Naming conventions For clarity and consistency, I recommend that you use the following directory structure and naming convention. module/ ├── manifests/ ├── lib/ └── spec/ ├── spec_helper.rb │ ├── classes/ │ └── _spec.rb │ ├── defines/ │ └── _spec.rb │ ├── applications/ │ └── _spec.rb │ ├── functions/ │ └── _spec.rb │ ├── types/ │ └── _spec.rb │ ├── type_aliases/ │ └── _spec.rb │ └── hosts/ └── _spec.rb ## Example groups If you use the above directory structure, your examples will automatically be placed in the correct groups and have access to the custom matchers. *If you choose not to*, you can force the examples into the required groups as follows. ```ruby describe 'myclass', :type => :class do ... end describe 'mydefine', :type => :define do ... end describe 'myapplication', :type => :application do ... end describe 'myfunction', :type => :puppet_function do ... end describe 'mytype', :type => :type do ... end describe 'My::TypeAlias', :type => :type_alias do ... end describe 'myhost.example.com', :type => :host do ... end ``` ## Defined Types, Classes & Applications ### Matchers #### Checking if the catalog compiles You can test whether the subject catalog compiles cleanly with `compile`. ```ruby it { is_expected.to compile } ``` To check the error messages of your class, you can check for raised error messages. ```ruby it { is_expected.to compile.and_raise_error(/error message match/) } ``` #### Checking if a resource exists You can test if a resource exists in the catalogue with the generic `contain_` matcher. ```ruby it { is_expected.to contain_augeas('bleh') } ``` You can also test if a class has been included in the catalogue with the same matcher. ```ruby it { is_expected.to contain_class('foo') } ``` Note that rspec-puppet does none of the class name parsing and lookup that the puppet parser would do for you. The matcher only accepts fully qualified classnames without any leading colons. That is a class `foo::bar` will only be matched by `foo::bar`, but not by `::foo::bar`, or `bar` alone. If your resource type includes :: (e.g. `foo::bar` simply replace the :: with __ (two underscores). ```ruby it { is_expected.to contain_foo__bar('baz') } ``` You can further test the parameters that have been passed to the resources with the generic `with_` chains. ```ruby it { is_expected.to contain_package('mysql-server').with_ensure('present') } ``` If you want to specify that the given parameters should be the only ones passed to the resource, use the `only_with_` chains. ```ruby it { is_expected.to contain_package('httpd').only_with_ensure('latest') } ``` You can use the `with` method to verify the value of multiple parameters. ```ruby it do is_expected.to contain_service('keystone').with( 'ensure' => 'running', 'enable' => 'true', 'hasstatus' => 'true', 'hasrestart' => 'true' ) end ``` The same holds for the `only_with` method, which in addition verifies the exact set of parameters and values for the resource in the catalogue. ```ruby it do is_expected.to contain_user('luke').only_with( 'ensure' => 'present', 'uid' => '501' ) end ``` You can also test that specific parameters have been left undefined with the generic `without_` chains. ```ruby it { is_expected.to contain_file('/foo/bar').without_mode } ``` You can use the without method to verify that a list of parameters have not been defined ```ruby it { is_expected.to contain_service('keystone').without( ['restart', 'status'] )} ``` #### Checking the number of resources You can test the number of resources in the catalogue with the `have_resource_count` matcher. ```ruby it { is_expected.to have_resource_count(2) } ``` The number of classes in the catalogue can be checked with the `have_class_count` matcher. ```ruby it { is_expected.to have_class_count(2) } ``` You can also test the number of a specific resource type, by using the generic `have__resource_count` matcher. ```ruby it { is_expected.to have_exec_resource_count(1) } ``` This last matcher also works for defined types. If the resource type contains ::, you can replace it with __ (two underscores). ```ruby it { is_expected.to have_logrotate__rule_resource_count(3) } ``` *NOTE*: when testing a class, the catalogue generated will always contain at least one class, the class under test. The same holds for defined types, the catalogue generated when testing a defined type will have at least one resource (the defined type itself). #### Relationship matchers The following methods will allow you to test the relationships between the resources in your catalogue, regardless of how the relationship is defined. This means that it doesn’t matter if you prefer to define your relationships with the metaparameters (**require**, **before**, **notify** and **subscribe**) or the chaining arrows (**->**, **~>**, **<-** and **<~**), they’re all tested the same. ```ruby it { is_expected.to contain_file('foo').that_requires('File[bar]') } it { is_expected.to contain_file('foo').that_comes_before('File[bar]') } it { is_expected.to contain_file('foo').that_notifies('File[bar]') } it { is_expected.to contain_file('foo').that_subscribes_to('File[bar]') } ``` An array can be used to test a resource for multiple relationships ```ruby it { is_expected.to contain_file('foo').that_requires(['File[bar]', 'File[baz]']) } it { is_expected.to contain_file('foo').that_comes_before(['File[bar]','File[baz]']) } it { is_expected.to contain_file('foo').that_notifies(['File[bar]', 'File[baz]']) } it { is_expected.to contain_file('foo').that_subscribes_to(['File[bar]', 'File[baz]']) } ``` You can also test the reverse direction of the relationship, so if you have the following bit of Puppet code ```ruby notify { 'foo': } notify { 'bar': before => Notify['foo'], } ``` You can test that **Notify[bar]** comes before **Notify[foo]** ```ruby it { is_expected.to contain_notify('bar').that_comes_before('Notify[foo]') } ``` Or, you can test that **Notify[foo]** requires **Notify[bar]** ```ruby it { is_expected.to contain_notify('foo').that_requires('Notify[bar]') } ``` ##### Match target syntax Note that this notation does not support any of the features you're used from the puppet language. Only a single resource with a single, unquoted title can be referenced here. Class names need to be always fully qualified and not have the leading `::`. It currently does not support inline arrays or quoting. These work * `Notify[foo]` * `Class[profile::apache]` These will not work * `Notify['foo']` * `Notify[foo, bar]` * `Class[::profile::apache]` ##### Recursive dependencies The relationship matchers are recursive in two directions: * vertical recursion, which checks for dependencies with parents of the resource (i.e. the resource is contained, directly or not, in the class involved in the relationship). E.g. where `Package['foo']` comes before `File['/foo']`: ```puppet class { 'foo::install': } -> class { 'foo::config': } class foo::install { package { 'foo': } } class foo::config { file { '/foo': } } ``` * horizontal recursion, which follows indirect dependencies (dependencies of dependencies). E.g. where `Yumrepo['foo']` comes before `File['/foo']`: ```puppet class { 'foo::repo': } -> class { 'foo::install': } -> class { 'foo::config': } class foo::repo { yumrepo { 'foo': } } class foo::install { package { 'foo': } } class foo::config { file { '/foo': } } ``` ##### Autorequires Autorequires are considered in dependency checks. #### Type matcher When testing custom types, the `be_valid_type` matcher provides a range of expectations: * `with_provider()`: check that the right provider was selected * `with_properties()`: check that the specified properties are available * `with_parameters()`: check that the specified parameters are available * `with_features()`: check that the specified features are available * `with_set_attributes()`: check that the specified attributes are set #### Type alias matchers When testing type aliases, the `allow_value` and `allow_values` matchers are used to check if the alias accepts particular values or not: ```ruby describe 'MyModule::Shape' do it { is_expected.to allow_value('square') } it { is_expected.to allow_values('circle', 'triangle') } it { is_expected.not_to allow_value('blue') } end ``` ### Writing tests #### Basic test structure To test that sysctl { 'baz' value => 'foo', } Will cause the following resource to be in included in catalogue for a host exec { 'sysctl/reload': command => '/sbin/sysctl -p /etc/sysctl.conf', } We can write the following testcase (in `spec/defines/sysctl_spec.rb`) ```ruby describe 'sysctl' do let(:title) { 'baz' } let(:params) { { :value => 'foo' } } it { is_expected.to contain_exec('sysctl/reload').with_command("/sbin/sysctl -p /etc/sysctl.conf") } end ``` #### Specifying the title of a resource ```ruby let(:title) { 'foo' } ``` #### Specifying the parameters to pass to a resources or parameterised class Parameters of a defined type, class or application can be passed defining `:params` in a let, and passing it a hash as seen below. ```ruby let(:params) { {:ensure => 'present', ...} } ``` For passing Puppet's `undef` as a paremeter value, you can simply use `:undef` and it will be translated to `undef` when compiling. For example: ```ruby let(:params) { {:user => :undef, ...} } ``` For references to nodes or resources as seen when using `require` or `before` properties, or an `application` resource you can pass the string as an argument to the `ref` helper: ```ruby let(:params) { :require => ref('Package', 'sudoku') } ``` Which translates to: ```puppet mydefine { 'mytitle': require => Package['sudoku'] } ``` Another example, for an application setup (when using `app_management`): ```ruby let(:params) { { :nodes => { ref('Node', 'dbnode') => ref('Myapp::Mycomponent', 'myapp') } } } ``` Will translate to: ```puppet site { myapp { 'myimpl': nodes => { Node['dbnode'] => Myapp::Mycomponent['myimpl'] } } } ``` #### Specifying the FQDN of the test node If the manifest you're testing expects to run on host with a particular name, you can specify this as follows ```ruby let(:node) { 'testhost.example.com' } ``` #### Specifying the environment name If the manifest you're testing expects to evaluate the environment name, you can specify this as follows ```ruby let(:environment) { 'production' } ``` #### Specifying the facts that should be available to your manifest By default, the test environment contains no facts for your manifest to use. You can set them with a hash ```ruby let(:facts) { {:operatingsystem => 'Debian', :kernel => 'Linux', ...} } ``` Facts may be expressed as a value (shown in the previous example) or a structure. Fact keys may be expressed as either symbols or strings. A key will be converted to a lower case string to align with the Facter standard ```ruby let(:facts) { {:os => { :family => 'RedHat', :release => { :major => '7', :minor => '1', :full => '7.1.1503' } } } } ``` You can also create a set of default facts provided to all specs in your spec_helper: ``` ruby RSpec.configure do |c| c.default_facts = { :operatingsystem => 'Ubuntu' } end ``` Any facts you provide with `let(:facts)` in a spec will automatically be merged on top of the default facts. #### Specifying top-scope variables that should be available to your manifest You can create top-scope variables much in the same way as an ENC. ```ruby let(:node_params) { { :hostgroup => 'webservers', :rack => 'KK04', :status => 'maintenance' } } ``` You can also create a set of default top-scope variables provided to all specs in your spec_helper: ``` ruby RSpec.configure do |c| c.default_node_params = { :owner => 'itprod', :site => 'ams4', :status => 'live' } end ``` **NOTE** Setting top-scope variables is not supported in Puppet < 3.0. #### Specifying extra code to load (pre-conditions) If the manifest being tested relies on another class or variables to be set, these can be added via a pre-condition. This code will be evaluated before the tested class. ```ruby let(:pre_condition) { 'include other_class' } ``` This may be useful when testing classes that are modular, e.g. testing `apache::mod::foo` which relies on a top-level `apache` class being included first. The value may be a raw string to be inserted into the Puppet manifest, or an array of strings (manifest fragments) that will be concatenated. #### Specifying extra code to load (post-conditions) In some cases, you may need to ensure that the code that you are testing comes **before** another set of code. Similar to the `:pre_condition` hook, you can add a `:post_condition` hook that will ensure that the added code is evaluated **after** the tested class. ```ruby let(:post_condition) { 'include other_class' } ``` This may be useful when testing classes that are modular, e.g. testing class `do_strange_things::to_the_catalog` which must come before class ``foo``. The value may be a raw string to be inserted into the Puppet manifest, or an array of strings (manifest fragments) that will be concatenated. #### Specifying the path to find your modules I recommend setting a default module path by adding the following code to your `spec_helper.rb` ```ruby RSpec.configure do |c| c.module_path = '/path/to/your/module/dir' end ``` However, if you want to specify it in each example, you can do so ```ruby let(:module_path) { '/path/to/your/module/dir' } ``` #### Specifying trusted facts When testing with Puppet >= 4.3 the trusted facts hash will have the standard trusted fact keys (certname, domain, and hostname) populated based on the node name (as set with `:node`). By default, the test environment contains no custom trusted facts (as usually obtained from certificate extensions) and found in the `extensions` key. If you need to test against specific custom certificate extensions you can set those with a hash. The hash will then be available in `$trusted['extensions']` ```ruby let(:trusted_facts) { {'pp_uuid' => 'ED803750-E3C7-44F5-BB08-41A04433FE2E', '1.3.6.1.4.1.34380.1.2.1' => 'ssl-termination'} } ``` You can also create a set of default certificate extensions provided to all specs in your spec_helper: ```ruby RSpec.configure do |c| c.default_trusted_facts = { 'pp_uuid' => 'ED803750-E3C7-44F5-BB08-41A04433FE2E', '1.3.6.1.4.1.34380.1.2.1' => 'ssl-termination' } end ``` #### Testing Exported Resources You can test if a resource was exported from the catalogue by using the `exported_resources` accessor in combination with any of the standard matchers. You can use `exported_resources` as the subject of a child context: ```ruby context 'exported resources' do subject { exported_resources } it { is_expected.to contain_file('foo') } end ``` You can also use `exported_resources` directly in a test: ```ruby it { expect(exported_resources).to contain_file('foo') } ``` #### Testing applications Applications in some ways behave as defined resources, but are more complex so require a number of elements already documented above to be combined for testing. A full example of the simplest rspec test for a single component application: ```ruby require 'spec_helper' describe 'orch_app' do let(:node) { 'my_node' } let(:title) { 'my_awesome_app' } let(:params) do { :nodes => { ref('Node', node) => ref('Orch_app::Db', title), } } end it { should compile } it { should contain_orch_app(title) } end ``` Each piece is required: * You must turn on app_management during testing for the handling to work * The `:node` definition is required to be set so later on you can reference it in the `:nodes` argument within `:params` * Applications act like defined resources, and each require a `:title` to be defined * The `:nodes` key in `:params` requires the use of node reference mappings to resource mappings. The `ref` keyword allows you to provide these (a normal string will not work). Beyond these requirements, the very basic `should compile` test and other matchers as you would expect will work the same as classes and defined resources. **Note:** for the moment, cross-node support is not available and will return an error. Ensure you model your tests to be single-node for the time being. ## Functions ### Matchers All of the standard RSpec matchers are available for you to use when testing Puppet functions. ```ruby it 'should be able to do something' do subject.call(['foo']) == 'bar' end ``` For your convenience though, a `run` matcher exists to provide easier to understand test cases. ```ruby it { is_expected.to run.with_params('foo').and_return('bar') } ``` ### Writing tests #### Basic test structure ```ruby require 'spec_helper' describe '' do ... end ``` #### Specifying the name of the function to test The name of the function must be provided in the top level description, e.g. ```ruby describe 'split' do ``` #### Specifying the arguments to pass to the function You can specify the arguments to pass to your function during the test(s) using either the `with_params` chain method in the `run` matcher ```ruby it { is_expected.to run.with_params('foo', 'bar', ['baz']) } ``` Or by using the `call` method on the subject directly ```ruby it 'something' do subject.call(['foo', 'bar', ['baz']]) end ``` #### Passing lambdas to the function A lambda (block) can be passed to functions that support either a required or optional lambda by passing a block to the `with_lambda` chain method in the `run` matcher. ```ruby it { is_expected.to run.with_lambda { |x| x * 2 } ``` #### Testing the results of the function You can test the result of a function (if it produces one) using either the `and_returns` chain method in the `run` matcher ```ruby it { is_expected.to run.with_params('foo').and_return('bar') } ``` Or by using any of the existing RSpec matchers on the subject directly ```ruby it 'something' do subject.call(['foo']) == 'bar' subject.call(['baz']).should be_an Array end ``` #### Testing the errors thrown by the function You can test whether the function throws an exception using either the `and_raises_error` chain method in the `run` matcher ```ruby it { is_expected.to run.with_params('a', 'b').and_raise_error(Puppet::ParseError) } it { is_expected.not_to run.with_params('a').and_raise_error(Puppet::ParseError) } ``` Or by using the existing `raises_error` RSpec matcher ```ruby it 'something' do expect { subject.call(['a', 'b']) }.should raise_error(Puppet::ParseError) expect { subject.call(['a']) }.should_not raise_error(Puppet::ParseError) end ``` #### Accessing the parser scope where the function is running Some complex functions require access to the current parser's scope, e.g. for stubbing other parts of the system. ```ruby before(:each) { scope.expects(:lookupvar).with('some_variable').returns('some_value') } it { is_expected.to run.with_params('...').and_return('...') } ``` Note that this does not work when testing manifests which use custom functions. Instead, you'll need to create a replacement function directly. ```ruby before(:each) do Puppet::Parser::Functions.newfunction(:custom_function, :type => :rvalue) { |args| raise ArgumentError, 'expected foobar' unless args[0] == 'foobar' 'expected value' } end ``` ## Hiera integration ### Configuration Set the hiera config symbol properly in your spec files: ```ruby let(:hiera_config) { 'spec/fixtures/hiera/hiera.yaml' } hiera = Hiera.new(:config => 'spec/fixtures/hiera/hiera.yaml') ``` Create your spec hiera files spec/fixtures/hiera/hiera.yaml ```ruby --- :backends: - yaml :hierarchy: - test :yaml: :datadir: 'spec/fixtures/hiera' ``` spec/fixtures/hiera/test.yaml ```ruby --- ntpserver: ['ntp1.domain.com','ntpXX.domain.com'] user: oneuser: shell: '/bin/bash' twouser: shell: '/sbin/nologin' ``` ### Use hiera in your tests ```ruby ntpserver = hiera.lookup('ntpserver', nil, nil) let(:params) { :ntpserver => ntpserver } ``` ### Enabling hiera lookups If you just want to fetch values from hiera (e.g. because you're testing code that uses explicit hiera lookups) just specify the path to the hiera config in your `spec_helper.rb` ```ruby RSpec.configure do |c| c.hiera_config = 'spec/fixtures/hiera/hiera.yaml' end ``` spec/fixtures/hiera/hiera.yaml ```yaml --- :backends: - yaml :yaml: :datadir: spec/fixtures/hieradata :hierarchy: - common ``` **Please note:** In-module hiera data depends on having a correct metadata.json file. It is strongly recommended that you use [metadata-json-lint](https://github.com/voxpupuli/metadata-json-lint) to automatically check your metadata.json file before running rspec. ## Producing coverage reports You can output a basic resource coverage report with the following in your `spec_helper.rb` ```ruby RSpec.configure do |c| c.after(:suite) do RSpec::Puppet::Coverage.report! end end ``` This checks which Puppet resources have been explicitly checked as part of the current test run and outputs both a coverage percentage and a list of untouched resources. A desired code coverage level can be provided. If this level is not achieved, a test failure will be raised. This can be used with a CI service, such as Jenkins or Bamboo, to enforce code coverage. The following example requires the code coverage to be at least 95%. ```ruby RSpec.configure do |c| c.after(:suite) do RSpec::Puppet::Coverage.report!(95) end end ``` Resources declared outside of the module being tested (i.e. forge dependencies) are automatically removed from the coverage report. There is one exception for this though: **prior to Puppet 4.6.0**, resources created by functions (create\_resources(), ensure\_package(), etc) did not have the required information in them to determine which manifest they came from and so can not be excluded from the coverage report. ## Related projects * [puppetlabs_spec_helper](https://github.com/puppetlabs/puppetlabs_spec_helper): shared spec helpers to setup puppet * [rspec-puppet-augeas](https://github.com/domcleal/rspec-puppet-augeas): RSpec tests for Augeas resources inside Puppet manifests * [jimdo-rspec-puppet-helpers](https://github.com/Jimdo/jimdo-rspec-puppet-helpers): Tests the contents of a file with a source * Fact providers * [rspec-puppet-facts](https://github.com/mcanevet/rspec-puppet-facts): Simplify your unit tests by looping on every supported Operating System and populating facts. * [rspec-puppet-osmash](https://github.com/Aethylred/rspec-puppet-osmash): Provides Operation System hashes and validations for rspec-puppet * [puppet_spec_facts](https://github.com/danieldreier/puppet_spec_facts): Gem to provide puppet fact hashes for rspec-puppet testing For a list of other module development tools see https://puppet.community/plugins/ rspec-puppet-2.6.1/Rakefile000066400000000000000000000002301312614575600156210ustar00rootroot00000000000000require 'rake' require 'rspec/core/rake_task' require 'bundler/gem_tasks' task :default => :test task :spec => :test RSpec::Core::RakeTask.new(:test) rspec-puppet-2.6.1/appveyor.yml000066400000000000000000000020631312614575600165520ustar00rootroot00000000000000build: off branches: only: - master # ruby versions under test environment: matrix: - RUBY_VERSION: 23-x64 PUPPET_GEM_VERSION: '~> 4.8.0' - RUBY_VERSION: 21 PUPPET_GEM_VERSION: '~> 4.8.0' - RUBY_VERSION: 23-x64 PUPPET_GEM_VERSION: '~> 4.2.0' - RUBY_VERSION: 21 PUPPET_GEM_VERSION: '~> 4.2.0' # Latest gem release - RUBY_VERSION: 23-x64 PUPPET_GEM_VERSION: '~> 4.0' # Latest code from puppetlabs/puppet.git - RUBY_VERSION: 23-x64 PUPPET_GEM_VERSION: 'https://github.com/puppetlabs/puppet.git#master' matrix: allow_failures: # Don't fail for puppet.git#master because it may be to blame for any failures - PUPPET_GEM_VERSION: 'https://github.com/puppetlabs/puppet.git#master' install: - SET PATH=C:\Ruby%RUBY_VERSION%\bin;%PATH% - SET LOG_SPEC_ORDER=true - ruby -v - gem -v - bundle -v - bundle install --jobs 4 --retry 2 --without development before_test: - type Gemfile.lock test_script: - bundle exec rake test notifications: email: - tim@bombasticmonkey.com rspec-puppet-2.6.1/bin/000077500000000000000000000000001312614575600147315ustar00rootroot00000000000000rspec-puppet-2.6.1/bin/rspec-puppet-init000077500000000000000000000006531312614575600202530ustar00rootroot00000000000000#!/usr/bin/env ruby $:.unshift File.join(File.dirname(__FILE__), *%w[.. lib]) require 'rspec-puppet' require 'optparse' options = { :module_name => nil, } OptionParser.new do |opts| opts.banner = "Usage: rspec-puppet-init [options]" opts.on('-n', '--name NAME', 'The name of the module (override autodetection)') do |v| options[:module_name] = v end end.parse! RSpec::Puppet::Setup.run(options[:module_name]) rspec-puppet-2.6.1/lib/000077500000000000000000000000001312614575600147275ustar00rootroot00000000000000rspec-puppet-2.6.1/lib/rspec-puppet.rb000066400000000000000000000046661312614575600177170ustar00rootroot00000000000000require 'puppet' require 'rspec' require 'fileutils' require 'tmpdir' require 'rspec-puppet/errors' require 'rspec-puppet/matchers' require 'rspec-puppet/example' require 'rspec-puppet/setup' require 'rspec-puppet/coverage' require 'rspec-puppet/adapters' begin require 'puppet/test/test_helper' rescue LoadError end RSpec.configure do |c| c.add_setting :enable_pathname_stubbing, :default => false end require 'rspec-puppet/monkey_patches' RSpec.configure do |c| c.add_setting :environmentpath, :default => '/etc/puppetlabs/code/environments' c.add_setting :module_path, :default => nil c.add_setting :manifest_dir, :default => nil c.add_setting :manifest, :default => nil c.add_setting :template_dir, :default => nil c.add_setting :config, :default => nil c.add_setting :confdir, :default => '/etc/puppet' c.add_setting :default_facts, :default => {} c.add_setting :default_node_params, :default => {} c.add_setting :default_trusted_facts, :default => {} c.add_setting :hiera_config, :default => '/dev/null' c.add_setting :parser, :default => 'current' c.add_setting :trusted_node_data, :default => false c.add_setting :ordering, :default => 'title-hash' c.add_setting :stringify_facts, :default => true c.add_setting :strict_variables, :default => false c.add_setting :adapter c.before(:all) do RSpec::Puppet::Setup.safe_setup_directories(nil, false) end if defined?(Puppet::Test::TestHelper) begin Puppet::Test::TestHelper.initialize rescue NoMethodError Puppet::Test::TestHelper.before_each_test end c.before :all do begin Puppet::Test::TestHelper.before_all_tests rescue end end c.after :all do begin Puppet::Test::TestHelper.after_all_tests rescue end end c.before :each do begin Puppet::Test::TestHelper.before_each_test rescue Puppet::Context::DuplicateRollbackMarkError Puppet::Test::TestHelper.send(:initialize_settings_before_each) rescue end end c.after :each do begin Puppet::Test::TestHelper.after_each_test rescue end end end c.before :each do if self.class.ancestors.include? RSpec::Puppet::Support @adapter = RSpec::Puppet::Adapters.get @adapter.setup_puppet(self) c.adapter = adapter end end c.before :each do |example| stub_file_consts(example) if self.respond_to?(:stub_file_consts) end end rspec-puppet-2.6.1/lib/rspec-puppet/000077500000000000000000000000001312614575600173565ustar00rootroot00000000000000rspec-puppet-2.6.1/lib/rspec-puppet/adapters.rb000066400000000000000000000163421312614575600215140ustar00rootroot00000000000000module RSpec::Puppet module Adapters class Base # Set up all Puppet settings applicable for this Puppet version as # application defaults. # # Puppet setting values can be taken from the global RSpec configuration, or from the currently # executing RSpec context. When a setting is specified both in the global configuration and in # the example group, the setting in the example group is preferred. # # @example Configuring a Puppet setting from a global RSpec configuration value # RSpec.configure do |config| # config.parser = "future" # end # # => Puppet[:parser] will be future # # @example Configuring a Puppet setting from within an RSpec example group # RSpec.describe 'my_module::my_class', :type => :class do # let(:module_path) { "/Users/luke/modules" } # #=> Puppet[:modulepath] will be "/Users/luke/modules" # end # # @example Configuring a Puppet setting with both a global RSpec configuration and local context # RSpec.configure do |config| # config.confdir = "/etc/puppet" # end # RSpec.describe 'my_module', :type => :class do # # Puppet[:confdir] will be "/etc/puppet" # end # RSpec.describe 'my_module::my_class', :type => :class do # let(:confdir) { "/etc/puppetlabs/puppet" } # # => Puppet[:confdir] will be "/etc/puppetlabs/puppet" in this example group # end # RSpec.describe 'my_module::my_define', :type => :define do # # Puppet[:confdir] will be "/etc/puppet" again # end # # @param example_group [RSpec::Core::ExampleGroup] The RSpec context to use for local settings # @return [void] def setup_puppet(example_group) settings = settings_map.map do |puppet_setting, rspec_setting| [puppet_setting, get_setting(example_group, rspec_setting)] end.flatten default_hash = {:confdir => '/dev/null', :vardir => '/dev/null' } if defined?(Puppet::Test::TestHelper) && Puppet::Test::TestHelper.respond_to?(:app_defaults_for_tests, true) default_hash.merge!(Puppet::Test::TestHelper.send(:app_defaults_for_tests)) end settings_hash = default_hash.merge(Hash[*settings]) if Puppet.settings.respond_to?(:initialize_app_defaults) Puppet.settings.initialize_app_defaults(settings_hash) else # Set settings the old way for Puppet 2.x, because that's how # they're defaulted in that version of Puppet::Test::TestHelper and # we won't be able to override them otherwise. settings_hash.each do |setting, value| Puppet.settings[setting] = value end end @environment_name = example_group.environment end def get_setting(example_group, rspec_setting) if example_group.respond_to?(rspec_setting) example_group.send(rspec_setting) else RSpec.configuration.send(rspec_setting) end end def catalog(node, exported) if exported # Use the compiler directly to skip the filtering done by the indirector Puppet::Parser::Compiler.compile(node).filter { |r| !r.exported? } else Puppet::Resource::Catalog.indirection.find(node.name, :use_node => node) end end def current_environment Puppet::Node::Environment.new(@environment_name) end def settings_map [ [:modulepath, :module_path], [:config, :config], [:confdir, :confdir], ] end def modulepath Puppet[:modulepath].split(File::PATH_SEPARATOR) end # @return [String, nil] The path to the Puppet manifest if it is present and set, nil otherwise. def manifest Puppet[:manifest] end end class Adapter4X < Base def setup_puppet(example_group) super if rspec_modulepath = RSpec.configuration.module_path modulepath = rspec_modulepath.split(File::PATH_SEPARATOR) else modulepath = Puppet[:environmentpath].split(File::PATH_SEPARATOR).map do |path| File.join(path, 'fixtures', 'modules') end end if rspec_manifest = RSpec.configuration.manifest manifest = rspec_manifest else manifest_paths = Puppet[:environmentpath].split(File::PATH_SEPARATOR).map do |path| File.join(path, 'fixtures', 'manifests') end manifest = manifest_paths.find do |path| File.exist?(path) end manifest ||= Puppet::Node::Environment::NO_MANIFEST end env = Puppet::Node::Environment.create(@environment_name, modulepath, manifest) loader = Puppet::Environments::Static.new(env) Puppet.push_context( { :environments => loader, :current_environment => env }, "Setup rspec-puppet environments" ) end def settings_map super.concat([ [:environmentpath, :environmentpath], [:hiera_config, :hiera_config], [:strict_variables, :strict_variables], [:manifest, :manifest], ]) end def catalog(node, exported) node.environment = current_environment # Override $::environment to workaround PUP-5835, where Puppet otherwise # stores a symbol for the parameter node.parameters['environment'] = current_environment.name.to_s if node.parameters['environment'] != node.parameters['environment'].to_s super end def current_environment Puppet.lookup(:current_environment) end def modulepath current_environment.modulepath end # Puppet 4.0 specially handles environments that don't have a manifest set, so we check for the no manifest value # and return nil when it is set. # # @return [String, nil] The path to the Puppet manifest if it is present and set, nil otherwise. def manifest m = current_environment.manifest if m == Puppet::Node::Environment::NO_MANIFEST nil else m end end end class Adapter3X < Base def settings_map super.concat([ [:manifestdir, :manifest_dir], [:manifest, :manifest], [:templatedir, :template_dir], [:hiera_config, :hiera_config], [:parser, :parser], [:trusted_node_data, :trusted_node_data], [:ordering, :ordering], [:stringify_facts, :stringify_facts], [:strict_variables, :strict_variables], ]) end end class Adapter27 < Base def settings_map super.concat([ [:manifestdir, :manifest_dir], [:manifest, :manifest], [:templatedir, :template_dir], ]) end end def self.get [ ['4.0', Adapter4X], ['3.0', Adapter3X], ['2.7', Adapter27] ].each do |(version, klass)| if Puppet::Util::Package.versioncmp(Puppet.version, version) >= 0 return klass.new end end raise "Puppet version #{Puppet.version} is not supported." end end end rspec-puppet-2.6.1/lib/rspec-puppet/cache.rb000066400000000000000000000013161312614575600207470ustar00rootroot00000000000000module RSpec::Puppet class Cache MAX_ENTRIES = 16 # @param [Proc] default_proc The default proc to use to fetch objects on cache miss def initialize(&default_proc) @default_proc = default_proc @cache = {} @lra = [] end def get(*args, &blk) # decouple the hash key from whatever the blk might do to it key = Marshal.load(Marshal.dump(args)) if !@cache.has_key? key @cache[key] = (blk || @default_proc).call(*args) @lra << key expire! end @cache[key] end private def expire! expired = @lra.slice!(0, @lra.size - MAX_ENTRIES) expired.each { |key| @cache.delete(key) } if expired end end end rspec-puppet-2.6.1/lib/rspec-puppet/coverage.rb000066400000000000000000000135661312614575600215110ustar00rootroot00000000000000unless defined?(RSpec::Core::NullReporter) module RSpec::Core class NullReporter def self.method_missing(*) # ignore end private_class_method :method_missing end end end module RSpec::Puppet class Coverage attr_accessor :filters class << self extend Forwardable def_delegators(:instance, :add, :cover!, :report!, :filters, :add_filter, :add_from_catalog, :results) attr_writer :instance def instance @instance ||= new end end def initialize @collection = {} @filters = ['Stage[main]', 'Class[Settings]', 'Class[main]', 'Node[default]'] end def add(resource) if !exists?(resource) && !filtered?(resource) @collection[resource.to_s] = ResourceWrapper.new(resource) end end def add_filter(type, title) def capitalize_name(name) name.split('::').map { |subtitle| subtitle.capitalize }.join('::') end type = capitalize_name(type) if type == 'Class' title = capitalize_name(title) end @filters << "#{type}[#{title}]" end # add all resources from catalog declared in module test_module def add_from_catalog(catalog, test_module) coverable_resources = catalog.to_a.reject { |resource| !test_module.nil? && filter_resource?(resource, test_module) } coverable_resources.each do |resource| add(resource) end end def filtered?(resource) filters.include?(resource.to_s) end def cover!(resource) if !filtered?(resource) && (wrapper = find(resource)) wrapper.touch! end end def report!(coverage_desired = nil) report = results puts <<-EOH.gsub(/^ {8}/, '') Total resources: #{report[:total]} Touched resources: #{report[:touched]} Resource coverage: #{report[:coverage]}% EOH if report[:coverage] != "100.00" puts <<-EOH.gsub(/^ {10}/, '') Untouched resources: #{ untouched_resources = report[:resources].reject do |_,rsrc| rsrc[:touched] end untouched_resources.inject([]) do |memo, (name,_)| memo << " #{name}" end.sort.join("\n") } EOH if coverage_desired coverage_test(coverage_desired, report[:coverage]) end end end def coverage_test(coverage_desired, coverage_actual) if coverage_desired.is_a?(Numeric) && coverage_desired.to_f <= 100.00 && coverage_desired.to_f >= 0.0 coverage_test = RSpec.describe("Code coverage.") coverage_results = coverage_test.example("Must be at least #{coverage_desired}% of code coverage") { expect( coverage_actual.to_f ).to be >= coverage_desired.to_f } coverage_test.run(RSpec::Core::NullReporter) passed = if coverage_results.execution_result.respond_to? :status then coverage_results.execution_result.status == :passed else coverage_results.execution_result[:status] == 'passed' end RSpec.configuration.reporter.example_failed coverage_results unless passed else puts "The desired coverage must be 0 <= x <= 100, not '#{coverage_desired.inspect}'" end end def results report = {} report[:total] = @collection.size report[:touched] = @collection.count { |_, resource| resource.touched? } report[:untouched] = report[:total] - report[:touched] report[:coverage] = "%5.2f" % ((report[:touched].to_f / report[:total].to_f) * 100) report[:resources] = Hash[*@collection.map do |name, wrapper| [name, wrapper.to_hash] end.flatten] report end private # Should this resource be excluded from coverage reports? # # The resource is not included in coverage reports if any of the conditions hold: # # * The resource has been explicitly filtered out. # * Examples: autogenerated resources such as 'Stage[main]' # * The resource is a class but does not belong to the module under test. # * Examples: Class dependencies included from a fixture module # * The resource was declared in a file outside of the test module or site.pp # * Examples: Resources declared in a dependency of this module. # # @param resource [Puppet::Resource] The resource that may be filtered # @param test_module [String] The name of the module under test # @return [true, false] def filter_resource?(resource, test_module) if @filters.include?(resource.to_s) return true end if resource.type == 'Class' module_name = resource.title.split('::').first.downcase if module_name != test_module return true end end if resource.file paths = module_paths(test_module) unless paths.any? { |path| resource.file.include?(path) } return true end end return false end # Find all paths that may contain testable resources for a module. # # @return [Array] def module_paths(test_module) adapter = RSpec.configuration.adapter paths = adapter.modulepath.map do |dir| File.join(dir, test_module, 'manifests') end paths << adapter.manifest if adapter.manifest paths end def find(resource) @collection[resource.to_s] end def exists?(resource) !find(resource).nil? end class ResourceWrapper attr_reader :resource def initialize(resource = nil) @resource = resource end def to_s @resource.to_s end def to_hash { :touched => touched?, } end def touch! @touched = true end def touched? !!@touched end end end end rspec-puppet-2.6.1/lib/rspec-puppet/errors.rb000066400000000000000000000042511312614575600212210ustar00rootroot00000000000000module RSpec::Puppet module Errors class MatchError < StandardError attr_reader :param, :expected, :actual, :negative def initialize(param, expected, actual, negative) @param = param @expected = expected @actual = actual @negative = negative end def message if @param.to_s == 'content' and expected.is_a?( String ) if negative == true "#{param} not set to supplied string" else "#{param} set to supplied string" end else if negative == true "#{param} not set to #{expected.inspect} but it is set to #{actual.inspect}" else "#{param} set to #{expected.inspect} but it is set to #{actual.inspect}" end end end def to_s message end end class RegexpMatchError < MatchError def message if negative == true "#{param} not matching #{expected.inspect} but its value of #{actual.inspect} does" else "#{param} matching #{expected.inspect} but its value of #{actual.inspect} does not" end end end class ProcMatchError < MatchError def message if negative == true "#{param} passed to the block would not return `#{expected.inspect}` but it did" else "#{param} passed to the block would return `#{expected.inspect}` but it is `#{actual.inspect}`" end end end class RelationshipError < StandardError attr_reader :from, :to def initialize(from, to) @from = from @to = to end def to_s message end end class BeforeRelationshipError < RelationshipError def message "that comes before #{to}" end end class RequireRelationshipError < RelationshipError def message "that requires #{to}" end end class NotifyRelationshipError < RelationshipError def message "that notifies #{to}" end end class SubscribeRelationshipError < RelationshipError def message "that is subscribed to #{to}" end end end end rspec-puppet-2.6.1/lib/rspec-puppet/example.rb000066400000000000000000000036051312614575600213420ustar00rootroot00000000000000require 'rspec-puppet/support' require 'rspec-puppet/example/define_example_group' require 'rspec-puppet/example/class_example_group' require 'rspec-puppet/example/function_example_group' require 'rspec-puppet/example/host_example_group' require 'rspec-puppet/example/type_example_group' require 'rspec-puppet/example/type_alias_example_group' require 'rspec-puppet/example/provider_example_group' require 'rspec-puppet/example/application_example_group' RSpec::configure do |c| def c.rspec_puppet_include(group, type, file_path) escaped_file_path = Regexp.compile(file_path.join('[\\\/]')) if RSpec::Version::STRING < '3' self.include group, :type => type, :example_group => { :file_path => escaped_file_path }, :spec_type => type else self.include group, :type => type, :file_path => lambda { |file_path, metadata| metadata[:type].nil? && escaped_file_path =~ file_path } end end c.rspec_puppet_include RSpec::Puppet::DefineExampleGroup, :define, %w[spec defines] c.rspec_puppet_include RSpec::Puppet::ClassExampleGroup, :class, %w[spec classes] c.rspec_puppet_include RSpec::Puppet::FunctionExampleGroup, :puppet_function, %w[spec functions] c.rspec_puppet_include RSpec::Puppet::HostExampleGroup, :host, %w[spec hosts] c.rspec_puppet_include RSpec::Puppet::TypeExampleGroup, :type, %w[spec types] c.rspec_puppet_include RSpec::Puppet::TypeAliasExampleGroup, :type_alias, %w[spec type_aliases] c.rspec_puppet_include RSpec::Puppet::ProviderExampleGroup, :provider, %w[spec providers] c.rspec_puppet_include RSpec::Puppet::ApplicationExampleGroup, :application, %w[spec applications] # Hook for each example group type to remove any caches or instance variables, since they will remain # and cause a memory leak. Can't be assigned per type by :file_path, so check for its presence. c.after(:each) { rspec_puppet_cleanup if respond_to?(:rspec_puppet_cleanup) } end rspec-puppet-2.6.1/lib/rspec-puppet/example/000077500000000000000000000000001312614575600210115ustar00rootroot00000000000000rspec-puppet-2.6.1/lib/rspec-puppet/example/application_example_group.rb000066400000000000000000000006531312614575600265740ustar00rootroot00000000000000module RSpec::Puppet # This module provides support for the application type module ApplicationExampleGroup include RSpec::Puppet::ManifestMatchers include RSpec::Puppet::Support def catalogue @catalogue ||= load_catalogue(:application) end def exported_resources lambda { load_catalogue(:application, true) } end def rspec_puppet_cleanup @catalogue = nil end end end rspec-puppet-2.6.1/lib/rspec-puppet/example/class_example_group.rb000066400000000000000000000005371312614575600253770ustar00rootroot00000000000000module RSpec::Puppet module ClassExampleGroup include RSpec::Puppet::ManifestMatchers include RSpec::Puppet::Support def catalogue @catalogue ||= load_catalogue(:class) end def exported_resources lambda { load_catalogue(:class, true) } end def rspec_puppet_cleanup @catalogue = nil end end end rspec-puppet-2.6.1/lib/rspec-puppet/example/define_example_group.rb000066400000000000000000000005421312614575600255200ustar00rootroot00000000000000module RSpec::Puppet module DefineExampleGroup include RSpec::Puppet::ManifestMatchers include RSpec::Puppet::Support def catalogue @catalogue ||= load_catalogue(:define) end def exported_resources lambda { load_catalogue(:define, true) } end def rspec_puppet_cleanup @catalogue = nil end end end rspec-puppet-2.6.1/lib/rspec-puppet/example/function_example_group.rb000066400000000000000000000141501312614575600261130ustar00rootroot00000000000000module RSpec::Puppet module FunctionExampleGroup include RSpec::Puppet::FunctionMatchers include RSpec::Puppet::ManifestMatchers include RSpec::Puppet::Support class V4FunctionWrapper attr_reader :func, :func_name def initialize(name, func, overrides) @func_name = name @func = func @overrides = overrides end # This method is used by the `run` matcher to trigger the function execution, and provides a uniform interface across all puppet versions. def execute(*args, &block) Puppet.override(@overrides, "rspec-test scope") do @func.call(@overrides[:global_scope], *freeze_arg(args), &block) end end # compatibility alias for existing tests def call(scope, *args) RSpec.deprecate("subject.call", :replacement => "is_expected.to run.with().and_raise_error(), or execute()") execute(*args) end private # Facts, keywords, single-quoted strings etc. are usually frozen in Puppet manifests, so freeze arguments to ensure functions are tested # under worst-case conditions. def freeze_arg(arg) case arg when Array arg.each { |a| freeze_arg(a) } arg.freeze when Hash arg.each { |k,v| freeze_arg(k); freeze_arg(v) } arg.freeze when String arg.freeze end arg end end class V3FunctionWrapper attr_accessor :func_name def initialize(name, func) @func_name = name @func = func end # This method is used by the `run` matcher to trigger the function execution, and provides a uniform interface across all puppet versions. def execute(*args) if args.nil? @func.call else @func.call(args) end end # This method was formerly used by the `run` matcher to trigger the function execution, and provides puppet versions dependant interface. def call(*args) RSpec.deprecate("subject.call", :replacement => "is_expected.to run.with().and_raise_error(), or execute()") if args.nil? @func.call else @func.call(*args) end end end # (at least) rspec 3.5 doesn't seem to memoize `subject` when called from # a before(:each) hook, so we need to memoize it ourselves. def subject @subject ||= find_function end def find_function(function_name = self.class.top_level_description) with_vardir do env = adapter.current_environment if Puppet.version.to_f >= 4.0 context_overrides = compiler.context_overrides func = nil loaders = Puppet.lookup(:loaders) Puppet.override(context_overrides, "rspec-test scope") do func = V4FunctionWrapper.new(function_name, loaders.private_environment_loader.load(:function, function_name), context_overrides) @scope = context_overrides[:global_scope] end return func if func.func end if Puppet::Parser::Functions.function(function_name) V3FunctionWrapper.new(function_name, scope.method("function_#{function_name}".intern)) else nil end end end def call_function(function_name, *args) # function = find_function(function_name) # function.execute(*args) scope.call_function(function_name, args) end def scope @scope ||= build_scope(compiler, nodename(:function)) end def catalogue @catalogue ||= compiler.catalog end def rspec_puppet_cleanup @subject = nil @catalogue = nil @compiler = nil @scope = nil end private def compiler @compiler ||= build_compiler end # get a compiler with an attached compiled catalog def build_compiler node_name = nodename(:function) fact_values = facts_hash(node_name) trusted_values = trusted_facts_hash(node_name) # Allow different Hiera configurations: HieraPuppet.instance_variable_set('@hiera', nil) if defined? HieraPuppet # if we specify a pre_condition, we should ensure that we compile that # code into a catalog that is accessible from the scope where the # function is called Puppet[:code] = pre_cond node_facts = Puppet::Node::Facts.new(node_name, fact_values.dup) node_options = { :parameters => fact_values, :facts => node_facts } stub_facts! fact_values node = build_node(node_name, node_options) if Puppet::Util::Package.versioncmp(Puppet.version, '4.3.0') >= 0 Puppet.push_context( { :trusted_information => Puppet::Context::TrustedInformation.new('remote', node_name, trusted_values) }, "Context for spec trusted hash" ) end compiler = Puppet::Parser::Compiler.new(node) compiler.compile if Puppet::Util::Package.versioncmp(Puppet.version, '4.0.0') >= 0 loaders = Puppet::Pops::Loaders.new(adapter.current_environment) Puppet.push_context( { :loaders => loaders, :global_scope => compiler.context_overrides[:global_scope] }, "set globals") end compiler end def build_scope(compiler, node_name) if Puppet.version.to_f >= 4.0 return compiler.context_overrides[:global_scope] elsif Puppet.version =~ /^2\.[67]/ # loadall should only be necessary prior to 3.x # Please note, loadall needs to happen first when creating a scope, otherwise # you might receive undefined method `function_*' errors Puppet::Parser::Functions.autoloader.loadall scope = Puppet::Parser::Scope.new(:compiler => compiler) else scope = Puppet::Parser::Scope.new(compiler) end scope.source = Puppet::Resource::Type.new(:node, node_name) scope.parent = compiler.topscope scope end def build_node(name, opts = {}) node_environment = adapter.current_environment opts.merge!({:environment => node_environment}) Puppet::Node.new(name, opts) end end end rspec-puppet-2.6.1/lib/rspec-puppet/example/host_example_group.rb000066400000000000000000000005341312614575600252440ustar00rootroot00000000000000module RSpec::Puppet module HostExampleGroup include RSpec::Puppet::ManifestMatchers include RSpec::Puppet::Support def catalogue @catalogue ||= load_catalogue(:host) end def exported_resources lambda { load_catalogue(:host, true) } end def rspec_puppet_cleanup @catalogue = nil end end end rspec-puppet-2.6.1/lib/rspec-puppet/example/provider_example_group.rb000066400000000000000000000000751312614575600261210ustar00rootroot00000000000000module RSpec::Puppet module ProviderExampleGroup end end rspec-puppet-2.6.1/lib/rspec-puppet/example/type_alias_example_group.rb000066400000000000000000000005061312614575600264200ustar00rootroot00000000000000module RSpec::Puppet module TypeAliasExampleGroup include RSpec::Puppet::TypeAliasMatchers include RSpec::Puppet::Support def catalogue(test_value) load_catalogue(:type_alias, false, :test_value => test_value) end def subject lambda { |test_value| catalogue(test_value) } end end end rspec-puppet-2.6.1/lib/rspec-puppet/example/type_example_group.rb000066400000000000000000000012341312614575600252460ustar00rootroot00000000000000module RSpec::Puppet module TypeExampleGroup include RSpec::Puppet::TypeMatchers include RSpec::Puppet::Support def subject @type_and_resource ||= begin setup_puppet type_name = self.class.top_level_description.downcase my_params = self.respond_to?(:params) ? params : {} [ Puppet::Type.type(type_name), # I don't want to create the resource here, so I have # to pass all of the bits form the current scope # required to create it title, my_params ] end end def rspec_puppet_cleanup @type_and_resource = nil end end end rspec-puppet-2.6.1/lib/rspec-puppet/matchers.rb000066400000000000000000000005421312614575600215120ustar00rootroot00000000000000require 'rspec-puppet/matchers/create_generic' require 'rspec-puppet/matchers/include_class' require 'rspec-puppet/matchers/compile' require 'rspec-puppet/matchers/run' require 'rspec-puppet/matchers/count_generic' require 'rspec-puppet/matchers/dynamic_matchers' require 'rspec-puppet/matchers/type_matchers' require 'rspec-puppet/matchers/allow_value' rspec-puppet-2.6.1/lib/rspec-puppet/matchers/000077500000000000000000000000001312614575600211645ustar00rootroot00000000000000rspec-puppet-2.6.1/lib/rspec-puppet/matchers/allow_value.rb000066400000000000000000000021711312614575600240240ustar00rootroot00000000000000module RSpec::Puppet module TypeAliasMatchers class AllowValue def initialize(values) @values = values @error_msgs = [] end def matches?(catalogue) matches = @values.map do |test_value| begin catalogue.call(test_value) true rescue Puppet::Error => e @error_msgs << e.message false end end matches.all? end def description if @values.length == 1 "match value #{@values.first.inspect}" else "match values #{@values.map(&:inspect).join(', ')}" end end def failure_message "expected that the type alias would " + description + " but it raised the #{@error_msgs.length == 1 ? 'error' : 'errors'} #{@error_msgs.join(', ')}" end def failure_message_when_negated "expected that the type alias would not " + description + " but it does" end end def allow_value(*values) RSpec::Puppet::TypeAliasMatchers::AllowValue.new(values) end alias_method :allow_values, :allow_value end end rspec-puppet-2.6.1/lib/rspec-puppet/matchers/compile.rb000066400000000000000000000112621312614575600231430ustar00rootroot00000000000000module RSpec::Puppet module ManifestMatchers class Compile def initialize @failed_resource = "" @check_deps = false @cycles = [] @error_msg = "" end def with_all_deps @check_deps = true self end def and_raise_error(error) @expected_error = error self end def matches?(catalogue) begin @catalogue = catalogue.call if cycles_found? false elsif @check_deps == true && missing_dependencies? false else @expected_error.nil? end rescue Puppet::Error => e @error_msg = e.message if @expected_error.nil? false else method = @expected_error.is_a?(Regexp) ? :=~ : :== e.message.send(method, @expected_error) end end end def description case @expected_error when nil "compile into a catalogue without dependency cycles" when Regexp "fail to compile and raise an error matching #{@expected_error.inspect}" else "fail to compile and raise the error #{@expected_error.inspect}" end end def failure_message unless @cycles.empty? "dependency cycles found: #{@cycles.join('; ')}" else unless @error_msg.empty? "error during compilation: #{@error_msg}" else case @expected_error when nil "expected that the catalogue would include #{@failed_resource}" when Regexp "expected that the catalogue would fail to compile and raise an error matching #{@expected_error.inspect}" else "expected that the catalogue would fail to compile and raise the error #{@expected_error.inspect}" end end end end def failure_message_when_negated if @expected_error.nil? "expected that the catalogue would not compile but it does" else "expected that the catalogue would compile but it does not" end end private def missing_dependencies? retval = false resource_vertices = @catalogue.vertices.select { |v| v.is_a? Puppet::Resource } resource_vertices.each do |vertex| vertex.each do |param,value| if [:require, :subscribe, :notify, :before].include? param value = Array[value] unless value.is_a? Array value.each do |val| if val.is_a? Puppet::Resource retval = true unless resource_exists?(val, vertex) end end end end end retval end def resource_hash @resource_hash ||= Proc.new do res_hash = {} @catalogue.vertices.each do |vertex| if vertex.is_a? Puppet::Resource res_hash[vertex.ref] = 1 if vertex[:alias] res_hash["#{vertex.type.to_s}[#{vertex[:alias]}]"] = 1 end if vertex.uniqueness_key != [vertex.title] res_hash["#{vertex.type.to_s}[#{vertex.uniqueness_key.first}]"] = 1 end end end res_hash end.call end def check_resource(res) if resource_hash[res.ref] true elsif res[:alias] && resource_hash["#{res.type.to_s}[#{res[:alias]}]"] true else false end end def resource_exists?(res, vertex) unless check_resource(res) @failed_resource = "#{res.ref} used at #{vertex.file}:#{vertex.line} in #{vertex.ref}" false else true end end def cycles_found? Puppet::Type.suppress_provider cat = @catalogue.to_ral.relationship_graph cat.write_graph(:resources) if cat.respond_to? :find_cycles_in_graph find_cycles(cat) else find_cycles_legacy(cat) end Puppet::Type.unsuppress_provider !@cycles.empty? end def find_cycles(catalogue) cycles = catalogue.find_cycles_in_graph if cycles.length > 0 cycles.each do |cycle| paths = catalogue.paths_in_cycle(cycle) @cycles << (paths.map{ |path| '(' + path.join(" => ") + ')'}.join("\n") + "\n") end end end def find_cycles_legacy(catalogue) begin catalogue.topsort rescue Puppet::Error => e @cycles = [e.message.rpartition(';').first.partition(':').last] end end end end end rspec-puppet-2.6.1/lib/rspec-puppet/matchers/count_generic.rb000066400000000000000000000040151312614575600243350ustar00rootroot00000000000000module RSpec::Puppet module ManifestMatchers class CountGeneric def initialize(type, count, *method) if type.nil? @type = method[0].to_s.gsub(/^have_(.+)_resource_count$/, '\1') else @type = type end @referenced_type = referenced_type(@type) @expected_number = count.to_i end def matches?(catalogue) @catalogue = catalogue.call if @type == "resource" @actual_number = @catalogue.resources.count do |res| !(['Class', 'Node'].include? res.type) end # Puppet automatically adds Stage[main] @actual_number = @actual_number - 1 else @actual_number = @catalogue.resources.count do |res| res.type == @referenced_type end # Puppet automatically adds Class[main] and Class[Settings] @actual_number = @actual_number - 2 if @type == "class" end @actual_number == @expected_number end def description desc = [] desc << "contain exactly #{@expected_number}" if @type == "class" desc << "#{@expected_number == 1 ? "class" : "classes" }" else unless @type == "resource" desc << "#{@referenced_type}" end desc << "#{@expected_number == 1 ? "resource" : "resources" }" end desc.join(" ") end def failure_message "expected that the catalogue would " + description + " but it contains #{@actual_number}" end def failure_message_when_negated "expected that the catalogue would not " + description + " but it does" end private def referenced_type(type) type.split('__').map { |r| r.capitalize }.join('::') end end def have_class_count(count) RSpec::Puppet::ManifestMatchers::CountGeneric.new('class', count) end def have_resource_count(count) RSpec::Puppet::ManifestMatchers::CountGeneric.new('resource', count) end end end rspec-puppet-2.6.1/lib/rspec-puppet/matchers/create_generic.rb000066400000000000000000000262611312614575600244570ustar00rootroot00000000000000require 'set' require 'rspec-puppet/matchers/parameter_matcher' module RSpec::Puppet module ManifestMatchers class CreateGeneric include RSpec::Puppet::Errors def initialize(*args, &block) @exp_resource_type = args.shift.to_s.gsub(/^(create|contain)_/, '') @args = args @block = block @referenced_type = referenced_type(@exp_resource_type) @title = args[0] @errors = [] @expected_params = [] @expected_undef_params = [] @notifies = [] @subscribes = [] @requires = [] @befores = [] end def with(*args, &block) params = args.shift @expected_params = @expected_params | params.to_a self end def only_with(*args, &block) params = args.shift @expected_params_count = (@expected_params_count || 0) + params.size self.with(params, &block) end def without(*args, &block) params = args.shift @expected_undef_params = @expected_undef_params | Array(params) self end def that_notifies(resource) @notifies.concat(Array(resource)) self end def that_subscribes_to(resource) @subscribes.concat(Array(resource)) self end def that_requires(resource) @requires.concat(Array(resource)) self end def that_comes_before(resource) @befores.concat(Array(resource)) self end def method_missing(method, *args, &block) if method.to_s =~ /^with_/ param = method.to_s.gsub(/^with_/, '') @expected_params << [param, args[0]] self elsif method.to_s =~ /^only_with_/ param = method.to_s.gsub(/^only_with_/, '') @expected_params_count = (@expected_params_count || 0) + 1 @expected_params << [param, args[0]] self elsif method.to_s =~ /^without_/ param = method.to_s.gsub(/^without_/, '') @expected_undef_params << [param, args[0]] self else super end end def matches?(catalogue) ret = true @catalogue = catalogue.is_a?(Puppet::Resource::Catalog) ? catalogue : catalogue.call resource = @catalogue.resource(@referenced_type, @title) if resource.nil? false else RSpec::Puppet::Coverage.cover!(resource) rsrc_hsh = resource.to_hash if resource.builtin_type? namevar = resource.resource_type.key_attributes.first.to_s else namevar = 'name' end unless @expected_params.any? { |param| param.first.to_s == namevar } rsrc_hsh.delete(namevar.to_sym) if rsrc_hsh.has_key?(namevar.to_sym) end if @expected_params_count unless rsrc_hsh.size == @expected_params_count ret = false (@errors ||= []) << "exactly #{@expected_params_count} parameters but the catalogue contains #{rsrc_hsh.size}" end end check_params(rsrc_hsh, @expected_params, :should) if @expected_params.any? check_params(rsrc_hsh, @expected_undef_params, :not) if @expected_undef_params.any? check_befores(@catalogue, resource) if @befores.any? check_requires(@catalogue, resource) if @requires.any? check_notifies(@catalogue, resource) if @notifies.any? check_subscribes(@catalogue, resource) if @subscribes.any? @errors.empty? end end def failure_message "expected that the catalogue would contain #{@referenced_type}[#{@title}]#{errors}" end def failure_message_when_negated "expected that the catalogue would not contain #{@referenced_type}[#{@title}]#{errors}" end def description values = [] value_str_prefix = "with" if @expected_params_count values << "exactly #{@expected_params_count} parameters" end if @expected_params.any? values.concat(generate_param_list(@expected_params, :should)) end if @expected_undef_params.any? values.concat(generate_param_list(@expected_undef_params, :not)) end if @notifies.any? value_str_prefix = "that notifies" values = @notifies end if @subscribes.any? value_str_prefix = "that subscribes to" values = @subscribes end if @requires.any? value_str_prefix = "that requires" values = @requires end if @befores.any? value_str_prefix = "that comes before" values = @befores end unless values.empty? if values.length == 1 value_str = " #{value_str_prefix} #{values.first}" else value_str = " #{value_str_prefix} #{values[0..-2].join(", ")} and #{values[-1]}" end end "contain #{@referenced_type}[#{@title}]#{value_str}" end def diffable? true end def expected @errors.map {|e| e.expected if e.respond_to?(:expected)}.compact.join("\n\n") end def actual @errors.map {|e| e.actual if e.respond_to?(:actual)}.compact.join("\n\n") end private def referenced_type(type) type.split('__').map { |r| r.capitalize }.join('::') end def errors @errors.empty? ? "" : " with #{@errors.join(', and parameter ')}" end def generate_param_list(list, type) output = [] list.each do |param, value| if value.nil? output << "#{param.to_s} #{type == :not ? 'un' : ''}defined" else a = type == :not ? '!' : '=' b = value.is_a?(Regexp) ? '~' : '>' if param.to_s == 'content' and value.is_a?( String ) output << "#{param.to_s} #{type == :not ? 'not ' : ''} supplied string" else output << "#{param.to_s} #{a}#{b} #{value.inspect}" end end end output end def check_befores(catalogue, resource) @befores.each do |ref| unless precedes?(resource, canonicalize_resource(ref)) @errors << BeforeRelationshipError.new(resource.to_ref, ref) end end end def check_requires(catalogue, resource) @requires.each do |ref| unless precedes?(canonicalize_resource(ref), resource) @errors << RequireRelationshipError.new(resource.to_ref, ref) end end end def check_notifies(catalogue, resource) @notifies.each do |ref| unless notifies?(resource, canonicalize_resource(ref)) @errors << NotifyRelationshipError.new(resource.to_ref, ref) end end end def check_subscribes(catalogue, resource) @subscribes.each do |ref| unless notifies?(canonicalize_resource(ref), resource) @errors << SubscribeRelationshipError.new(resource.to_ref, ref) end end end def resource_ref(resource) resource.respond_to?(:to_ref) ? resource.to_ref : resource end def resource_from_ref(ref) ref.is_a?(Puppet::Resource) ? ref : @catalogue.resource(ref) end def canonicalize_resource(resource) res = resource_from_ref(resource_ref(resource)) if res.nil? resource = Struct.new(:type, :title).new(*@catalogue.title_key_for_ref(resource)) if resource.is_a?(String) res = @catalogue.resource_keys.select { |type, name| type == resource.type }.map { |type, name| @catalogue.resource(type, name) }.compact.find { |cat_res| cat_res.builtin_type? && cat_res.uniqueness_key.first == resource.title } end res end def canonicalize_resource_ref(ref) resource_ref(resource_from_ref(ref)) end def relationship_refs(resource, type, visited = Set.new) resource = canonicalize_resource(resource) results = Set.new return results unless resource # guard to prevent infinite recursion if visited.include?(resource.object_id) return [canonicalize_resource_ref(resource)] else visited << resource.object_id end Array[resource[type]].flatten.compact.each do |r| results << canonicalize_resource_ref(r) results << relationship_refs(r, type, visited) res = canonicalize_resource(r) if res && res.builtin_type? results << res.to_ref results << "#{res.type.to_s.capitalize}[#{res.uniqueness_key.first}]" end end Puppet::Type.suppress_provider # Add autorequires if any if type == :require and resource.resource_type.respond_to? :eachautorequire resource.resource_type.eachautorequire do |t, b| Array(resource.to_ral.instance_eval(&b)).each do |dep| res = "#{t.to_s.capitalize}[#{dep}]" if r = relationship_refs(res, type, visited) results << res results << r end end end end Puppet::Type.unsuppress_provider results.flatten end def self_or_upstream(vertex) [vertex] + @catalogue.upstream_from_vertex(vertex).keys end def precedes?(first, second) return false if first.nil? || second.nil? self_or_upstream(first).each do |u| self_or_upstream(second).each do |v| before_refs = relationship_refs(u, :before) + relationship_refs(u, :notify) require_refs = relationship_refs(v, :require) + relationship_refs(u, :subscribe) if before_refs.include?(v.to_ref) || require_refs.include?(u.to_ref) || (before_refs & require_refs).any? return true end end end # Nothing found return false end def notifies?(first, second) return false if first.nil? || second.nil? self_or_upstream(first).each do |u| self_or_upstream(second).each do |v| notify_refs = relationship_refs(u, :notify) subscribe_refs = relationship_refs(v, :subscribe) if notify_refs.include?(v.to_ref) || subscribe_refs.include?(u.to_ref) return true end end end # Nothing found return false end # @param resource [Hash] The resource in the catalog # @param list [Array] The expected values of the resource # @param type [:should, :not] Whether the given parameters should/not match def check_params(resource, list, type) list.each do |param, value| param = param.to_sym if value.nil? then unless resource[param].nil? @errors << "#{param} undefined but it is set to #{resource[param].inspect}" end else m = ParameterMatcher.new(param, value, type) unless m.matches?(resource) @errors.concat m.errors end end end end end end end rspec-puppet-2.6.1/lib/rspec-puppet/matchers/dynamic_matchers.rb000066400000000000000000000014731312614575600250300ustar00rootroot00000000000000module RSpec::Puppet module ManifestMatchers def method_missing(method, *args, &block) return RSpec::Puppet::ManifestMatchers::CreateGeneric.new(method, *args, &block) if method.to_s =~ /^(create|contain)_/ return RSpec::Puppet::ManifestMatchers::CountGeneric.new(nil, args[0], method) if method.to_s =~ /^have_.+_count$/ return RSpec::Puppet::ManifestMatchers::Compile.new if method == :compile super end end module FunctionMatchers def method_missing(method, *args, &block) return RSpec::Puppet::FunctionMatchers::Run.new if method == :run super end end module TypeMatchers def method_missing(method, *args, &block) return RSpec::Puppet::TypeMatchers::CreateGeneric.new(method, *args, &block) if method == :be_valid_type super end end end rspec-puppet-2.6.1/lib/rspec-puppet/matchers/include_class.rb000066400000000000000000000013101312614575600243140ustar00rootroot00000000000000module RSpec::Puppet module ManifestMatchers extend RSpec::Matchers::DSL matcher :include_class do |expected_class| match do |catalogue| RSpec.deprecate(:include_class, :replacement => :contain_class) catalogue.call.classes.include?(expected_class) end description do "include Class[#{expected_class}]" end if RSpec::Version::STRING < '3' failure_message_for_should do |actual| "expected that the catalogue would include Class[#{expected_class}]" end else failure_message do |actual| "expected that the catalogue would include Class[#{expected_class}]" end end end end end rspec-puppet-2.6.1/lib/rspec-puppet/matchers/parameter_matcher.rb000066400000000000000000000065761312614575600252120ustar00rootroot00000000000000module RSpec::Puppet module ManifestMatchers class ParameterMatcher include RSpec::Puppet::Errors # @param parameter [Symbol] The specific parameter to check # @param value [Object] The expected data to match the parameter against # @param type [:should, :not] Whether the given parameter should match def initialize(parameter, value, type) @parameter, @value, @type = parameter, value, type @should_match = (type == :should) @errors = [] end # Ensure that the actual parameter matches the expected parameter. # # @param resource [Hash] A hash representing a Puppet # resource in the catalog # # @return [true, false] def matches?(resource) @resource = resource actual = @resource[@parameter] expected = @value # Puppet flattens an array with a single value into just the value and # this can cause confusion when testing as people expect when you put # an array in, you'll get an array out. actual = [actual] if expected.is_a?(Array) && !actual.is_a?(Array) retval = check(expected, actual) unless retval @errors << MatchError.new(@parameter, expected, actual, !@should_match) end retval end # @!attribute [r] errors # @return [Array] All expectation errors # generated on this parameter. attr_reader :errors private # Recursively check that the `expected` and `actual` data structures match # # @param expected [Object] The expected value of the given resource param # @param actual [Object] The value of the resource as found in the catalogue # # @return [true, false] If the resource matched def check(expected, actual) return false if !expected.is_a?(Proc) && actual.nil? && !expected.nil? case expected when Proc check_proc(expected, actual) when Regexp check_regexp(expected, actual) when Hash check_hash(expected, actual) when Array check_array(expected, actual) else check_string(expected, actual) end end def check_proc(expected, actual) expected_return = @should_match actual_return = expected.call(actual) actual_return == expected_return end def check_regexp(expected, actual) !!(actual.to_s.match expected) == @should_match end # Ensure that two hashes have the same number of keys, and that for each # key in the expected hash, there's a stringified key in the actual hash # with a matching value. def check_hash(expected, actual) op = @should_match ? :"==" : :"!=" unless expected.keys.size.send(op, actual.keys.size) return false end expected.keys.all? do |key| check(expected[key], actual[key]) end end def check_array(expected, actual) op = @should_match ? :"==" : :"!=" unless expected.size.send(op, actual.size) return false end (0...expected.size).all? do |index| check(expected[index], actual[index]) end end def check_string(expected, actual) (expected.to_s == actual.to_s) == @should_match end end end end rspec-puppet-2.6.1/lib/rspec-puppet/matchers/run.rb000066400000000000000000000105561312614575600223240ustar00rootroot00000000000000module RSpec::Puppet module FunctionMatchers class Run def matches?(func_obj) @func_obj = func_obj @has_returned = false begin # `*nil` does not evaluate to "no params" on ruby 1.8 :-( @actual_return = @params.nil? ? @func_obj.execute(&@block) : @func_obj.execute(*@params, &@block) @has_returned = true rescue Exception => e @actual_error = e end if @has_expected_error if @has_returned return false elsif @actual_error.is_a?(@expected_error) case @expected_error_message when nil return true when Regexp return !!(@actual_error.message =~ @expected_error_message) else return @actual_error.message == @expected_error_message end else # error did not match return false end elsif @has_expected_return if !@has_returned return false else case @expected_return when Regexp return !!(@actual_return =~ @expected_return) else return @actual_return == @expected_return end end else return @has_returned end end def with_params(*params) @params = params # stringify immediately to protect us from the params being changed by # the subject, e.g. with params.shift @func_args = @params.inspect[1..-2] self end def with_lambda(&block) @block = block self end def and_return(value) @has_expected_return = true @expected_return = value if value.is_a? Regexp @desc = "match #{value.inspect}" else @desc = "return #{value.inspect}" end self end def and_raise_error(error_or_message, message=nil) @has_expected_error = true case error_or_message when String, Regexp @expected_error, @expected_error_message = Exception, error_or_message else @expected_error, @expected_error_message = error_or_message, message end if @expected_error_message.is_a? Regexp @desc = "raise an #{@expected_error} with the message matching #{@expected_error_message.inspect}" else @desc = "raise an #{@expected_error}" unless @expected_error_message.nil? @desc += "with the message #{@expected_error_message.inspect}" end end self end def failure_message failure_message_generic(:should, @func_obj) end def failure_message_when_negated failure_message_generic(:should_not, @func_obj) end def description if @desc "run #{func_name}(#{func_params}) and #{@desc}" else "run #{func_name}(#{func_params}) without error" end end private def func_name @func_obj.func_name end def func_params @func_args end def failure_message_actual(type) if type != :should '' elsif @actual_error if @has_expected_return " instead of raising #{@actual_error.class.inspect}(#{@actual_error})\n#{@actual_error.backtrace.join("\n")}" else " instead of #{@actual_error.class.inspect}(#{@actual_error})\n#{@actual_error.backtrace.join("\n")}" end else # function has returned if @has_expected_error " instead of returning #{@actual_return.inspect}" else " instead of #{@actual_return.inspect}" end end end def failure_message_generic(type, func_obj) message = "expected #{func_name}(#{func_params}) to " message << "not " if type == :should_not if @has_expected_return message << "have returned #{@expected_return.inspect}" else if @has_expected_error message << "have raised #{@expected_error.inspect}" if @expected_error_message message << " matching #{@expected_error_message.inspect}" end else message << "have run successfully" end end message << failure_message_actual(type) end end end end rspec-puppet-2.6.1/lib/rspec-puppet/matchers/type_matchers.rb000066400000000000000000000100341312614575600243560ustar00rootroot00000000000000module RSpec::Puppet module TypeMatchers class CreateGeneric def initialize(*args, &block) @exp_provider = nil @exp_parameters = [] @exp_properties = [] @exp_features = [] @exp_defaults = {} @params_with_values = {} @errors = [] end # specifies a provider to validate def with_provider(name) @exp_provider = name self end # ensures the listed properties are valid def with_properties(props) @exp_properties = @exp_properties | Array(props) self end # ensures the listed parameters are valid def with_parameters(params) @exp_parameters = @exp_parameters | Array(params) self end # ensure the type has the list of features def with_features(features) @exp_features = @exp_features | Array(features) self end # # ensures that the specified parameters with their values # results in a valid resource # def with_set_attributes(params) @params_with_values.merge!(params) self end def with_defaults(defaults_hash) @exp_defaults.merge!(defaults_hash) self end #def with_autorequires(autorequires)) #end # # this is the method that drives all of the validation # def matches?(type_title_and_params) type = type_title_and_params[0] title = type_title_and_params[1] params = type_title_and_params[2] unless match_params(type) && match_props(type) && match_features(type) return false end if @params_with_values != {} || @exp_provider # only build a resource if we are validating provider or setting # additional parameters resource = be_valid_resource(type, title, params.merge(@params_with_values)) match_default_provider(resource) and match_default_values(resource) else true end end # checks that the specified params exist def match_params(type) match_attrs(type, @exp_parameters, :parameter) end # checks that the specified properties exist def match_props(type) match_attrs(type, @exp_properties, :property) end # checks that the specified features exist def match_features(type) match_attrs(type, @exp_features, :feature) end # builds the resource with the specified param values def be_valid_resource(type, title, params) params[:name] ||= title type.new(params) end # # checks that the expected provider is set # def match_default_provider(resource) if @exp_provider if resource[:provider] == @exp_provider return true else @errors.push("Expected provider: #{@exp_provider} does not match: #{resource[:provider]}") return false end else return true end end def match_default_values(resource) # TODO FINISH true end def description "be a valid type" end def failure_message "Not a valid type #{@errors.inspect}" end private def match_attrs(type, attrs, attr_type) baddies = [] attrs.each do |param| param = param.to_sym if attr_type == :feature unless type.provider_feature(param) baddies.push(param) end elsif ! type.send("valid#{attr_type}?".to_sym, param) baddies.push(param) end end if baddies.size > 0 @errors.push("Invalid #{pluralize(attr_type)}: #{baddies.join(',')}") false else true end end def pluralize(name) if name == :property "properties" else "#{name}s" end end end end end rspec-puppet-2.6.1/lib/rspec-puppet/monkey_patches.rb000066400000000000000000000115551312614575600227230ustar00rootroot00000000000000require 'pathname' module Puppet # Allow rspec-puppet to prevent Puppet::Type from automatically picking # a provider for a resource. We need to do this because in order to fully # resolve the graph edges, we have to convert the Puppet::Resource objects # into Puppet::Type objects so that their autorequires are evaluated. We need # to prevent provider code from being called during this process as it's very # platform specific. class Type old_set_default = instance_method(:set_default) define_method(:set_default) do |attr| old_posix = nil old_microsoft_windows = nil if attr == :provider old_posix = Puppet.features.posix? old_microsoft_windows = Puppet.features.microsoft_windows? if Puppet::Util::Platform.pretend_windows? Puppet.features.add(:posix) { false } Puppet.features.add(:microsoft_windows) { true } else Puppet.features.add(:posix) { true } Puppet.features.add(:microsoft_windows) { false } end end retval = old_set_default.bind(self).call(attr) unless old_posix.nil? Puppet.features.add(:posix) { old_posix } end unless old_microsoft_windows.nil? Puppet.features.add(:microsoft_windows) { old_microsoft_windows } end retval end def self.suppress_provider? @suppress_provider ||= false end def self.suppress_provider @suppress_provider = true end def self.unsuppress_provider @suppress_provider = false end end # If Puppet::Node::Environment has a validate_dirs instance method (i.e. # Puppet < 3.x), wrap the method to check if rspec-puppet is pretending to be # running under windows. The original method uses Puppet::Util.absolute_path? # (which in turn calls Puppet::Util::Platform.windows?) to validate the path # to the manifests on disk during compilation, so we have to temporarily # disable the pretending when running it. class Node::Environment if instance_methods.include?("validate_dirs") old_validate_dirs = instance_method(:validate_dirs) define_method(:validate_dirs) do |dirs| pretending = Puppet::Util::Platform.pretend_platform if pretending Puppet::Util::Platform.pretend_to_be nil end output = old_validate_dirs.bind(self).call(dirs) Puppet::Util::Platform.pretend_to_be pretending output end end end module Util # Allow rspec-puppet to pretend to be different platforms. module Platform def windows? pretend_platform.nil? ? (actual_platform == :windows) : pretend_windows? end module_function :windows? def actual_platform @actual_platform ||= !!File::ALT_SEPARATOR ? :windows : :posix end module_function :actual_platform def pretend_windows? pretend_platform == :windows end module_function :pretend_windows? def pretend_to_be(platform) # Ensure that we cache the real platform before pretending to be # a different one actual_platform @pretend_platform = platform end module_function :pretend_to_be def pretend_platform @pretend_platform ||= nil end module_function :pretend_platform end end end class Pathname def rspec_puppet_basename(path) raise ArgumentError, 'pathname stubbing not enabled' unless RSpec.configuration.enable_pathname_stubbing if path =~ /\A[a-zA-Z]:(#{SEPARATOR_PAT}.*)\z/ path = path[2..-1] end path.split(SEPARATOR_PAT).last || path[/(#{SEPARATOR_PAT})/, 1] || path end if instance_methods.include?("chop_basename") old_chop_basename = instance_method(:chop_basename) define_method(:chop_basename) do |path| if RSpec.configuration.enable_pathname_stubbing base = rspec_puppet_basename(path) if /\A#{SEPARATOR_PAT}?\z/o =~ base return nil else return path[0, path.rindex(base)], base end else old_chop_basename.bind(self).call(path) end end end end # Prevent the File type from munging paths (which uses File.expand_path to # normalise paths, which does very bad things to *nix paths on Windows. Puppet::Type.type(:file).paramclass(:path).munge { |value| value } # Prevent the Exec type from validating the user. This parameter isn't # supported under Windows at all and only under *nix when the current user is # root. Puppet::Type.type(:exec).paramclass(:user).validate { |value| true } # Prevent Puppet from requiring 'puppet/util/windows' if we're pretending to be # windows, otherwise it will require other libraries that probably won't be # available on non-windows hosts. module Kernel alias :old_require :require def require(path) return if path == 'puppet/util/windows' && Puppet::Util::Platform.pretend_windows? old_require(path) end end rspec-puppet-2.6.1/lib/rspec-puppet/rake_task.rb000066400000000000000000000012241312614575600216460ustar00rootroot00000000000000require 'rake' require 'rspec/core/rake_task' desc "Run all RSpec code examples" RSpec::Core::RakeTask.new(:rspec) do |t| File.exist?('spec/spec.opts') ? opts = File.read("spec/spec.opts").chomp : opts = "" t.rspec_opts = opts end SPEC_SUITES = (Dir.entries('spec') - ['.', '..','fixtures']).select {|e| File.directory? "spec/#{e}" } namespace :rspec do SPEC_SUITES.each do |suite| desc "Run #{suite} RSpec code examples" RSpec::Core::RakeTask.new(suite) do |t| t.pattern = "spec/#{suite}/**/*_spec.rb" File.exist?('spec/spec.opts') ? opts = File.read("spec/spec.opts").chomp : opts = "" t.rspec_opts = opts end end end rspec-puppet-2.6.1/lib/rspec-puppet/raw_string.rb000066400000000000000000000006051312614575600220630ustar00rootroot00000000000000module RSpec::Puppet # A raw string object, that is used by helpers to allow consumers to return non-quoted strings # as part of their params section. class RawString # Create a new RawString object # @param [String] value string to wrap def initialize(value) @value = value end # @return [String] raw string def inspect @value end end end rspec-puppet-2.6.1/lib/rspec-puppet/setup.rb000066400000000000000000000112321312614575600210420ustar00rootroot00000000000000require 'puppet' if Puppet.version.to_f >= 4.0 require 'puppet/pops' end require 'fileutils' module RSpec::Puppet class Setup def self.run(module_name=nil) unless is_module_dir? $stderr.puts "Does not appear to be a Puppet module. Aborting" return false end safe_setup_directories(module_name) safe_touch(File.join('spec', 'fixtures', 'manifests', 'site.pp')) safe_create_spec_helper safe_create_rakefile end def self.safe_setup_directories(module_name=nil, verbose=true) if module_name.nil? module_name = get_module_name if module_name.nil? $stderr.puts "Unable to determine module name. Aborting" return false end end [ 'spec', File.join('spec', 'classes'), File.join('spec', 'defines'), File.join('spec', 'functions'), File.join('spec', 'hosts'), File.join('spec', 'fixtures'), File.join('spec', 'fixtures', 'manifests'), File.join('spec', 'fixtures', 'modules'), ].each { |dir| safe_mkdir(dir, verbose) } target = File.join('spec', 'fixtures', 'modules', module_name) safe_make_link('.', target, verbose) end def self.safe_teardown_links(module_name=nil) if module_name.nil? module_name = get_module_name if module_name.nil? $stderr.puts "Unable to determine module name. Aborting" return false end end target = File.join('spec', 'fixtures', 'modules', module_name) if File.symlink?(target) && File.readlink(target) == File.expand_path('.') File.unlink(target) end end protected def self.get_module_name module_name = nil Dir["manifests/*.pp"].entries.each do |manifest| module_name = get_module_name_from_file(manifest) break unless module_name.nil? end module_name end def self.get_module_name_from_file(file) # FIXME: see discussion at # https://github.com/rodjek/rspec-puppet/issues/290 if Puppet.version.to_f >= 4.0 p = Puppet::Pops::Parser::Lexer2.new else p = Puppet::Parser::Lexer.new end module_name = nil p.string = File.read(file) tokens = p.fullscan i = tokens.index { |token| [:CLASS, :DEFINE].include? token.first } unless i.nil? module_name = tokens[i + 1].last[:value].split('::').first end module_name end def self.is_module_dir? Dir["*"].entries.include? "manifests" end def self.safe_mkdir(dir, verbose=true) if File.exists? dir unless File.directory? dir $stderr.puts "!! #{dir} already exists and is not a directory" end else FileUtils.mkdir dir puts " + #{dir}/" if verbose end end def self.safe_touch(file) if File.exists? file unless File.file? file $stderr.puts "!! #{file} already exists and is not a regular file" end else FileUtils.touch file puts " + #{file}" end end def self.safe_create_file(filename, content) if File.exists? filename old_content = File.read(filename) if old_content != content $stderr.puts "!! #{filename} already exists and differs from template" end else File.open(filename, 'w') do |f| f.puts content end puts " + #{filename}" end end def self.safe_create_spec_helper content = File.read(File.expand_path(File.join(__FILE__, '..', 'spec_helper.rb'))) safe_create_file('spec/spec_helper.rb', content) end def self.safe_make_link(source, target, verbose=true) if File.exists?(target) unless File.symlink?(target) && File.readlink(target) == File.expand_path(source) $stderr.puts "!! #{target} already exists and is not a symlink" end else if Puppet::Util::Platform.windows? output = `call mklink /J "#{target.gsub('/', '\\')}" "#{source}"` unless $?.success? puts output abort end else FileUtils.ln_s(File.expand_path(source), target) end puts " + #{target}" if verbose end end def self.safe_create_rakefile content = <<-'EOF' require 'rspec-puppet/rake_task' begin if Gem::Specification::find_by_name('puppet-lint') require 'puppet-lint/tasks/puppet-lint' PuppetLint.configuration.ignore_paths = ["spec/**/*.pp", "vendor/**/*.pp"] task :default => [:rspec, :lint] end rescue Gem::LoadError task :default => :rspec end EOF safe_create_file('Rakefile', content) end end end rspec-puppet-2.6.1/lib/rspec-puppet/spec_helper.rb000066400000000000000000000005561312614575600222020ustar00rootroot00000000000000require 'rspec-puppet' fixture_path = File.join(File.dirname(File.expand_path(__FILE__)), 'fixtures') RSpec.configure do |c| c.module_path = File.join(fixture_path, 'modules') c.manifest_dir = File.join(fixture_path, 'manifests') c.manifest = File.join(fixture_path, 'manifests', 'site.pp') c.environmentpath = File.join(Dir.pwd, 'spec') end rspec-puppet-2.6.1/lib/rspec-puppet/support.rb000066400000000000000000000301361312614575600214220ustar00rootroot00000000000000require 'rspec-puppet/cache' require 'rspec-puppet/adapters' require 'rspec-puppet/raw_string' module RSpec::Puppet module Support @@cache = RSpec::Puppet::Cache.new def subject lambda { catalogue } end def environment 'rp_env' end def build_code(type, manifest_opts) if Puppet.version.to_f >= 4.0 or Puppet[:parser] == 'future' [site_pp_str, pre_cond, test_manifest(type, manifest_opts), post_cond].compact.join("\n") else [import_str, pre_cond, test_manifest(type, manifest_opts), post_cond].compact.join("\n") end end def guess_type_from_path(path) case path when /spec\/defines/ :define when /spec\/classes/ :class when /spec\/functions/ :function when /spec\/hosts/ :host when /spec\/types/ :type when /spec\/type_aliases/ :type_alias when /spec\/provider/ :provider when /spec\/applications/ :application else :unknown end end def stub_file_consts(example) if example.respond_to?(:metadata) type = example.metadata[:type] else type = guess_type_from_path(example.example.metadata[:file_path]) end munged_facts = facts_hash(nodename(type)) if munged_facts['operatingsystem'] && munged_facts['operatingsystem'].to_s.downcase == 'windows' stub_const_wrapper('File::PATH_SEPARATOR', ';') stub_const_wrapper('File::ALT_SEPARATOR', "\\") stub_const_wrapper('Pathname::SEPARATOR_PAT', /[#{Regexp.quote(File::ALT_SEPARATOR)}#{Regexp.quote(File::SEPARATOR)}]/) else stub_const_wrapper('File::PATH_SEPARATOR', ':') stub_const_wrapper('File::ALT_SEPARATOR', nil) stub_const_wrapper('Pathname::SEPARATOR_PAT', /#{Regexp.quote(File::SEPARATOR)}/) end end def stub_const_wrapper(const, value) if defined?(RSpec::Core::MockingAdapters::RSpec) && RSpec.configuration.mock_framework == RSpec::Core::MockingAdapters::RSpec stub_const(const, value) else klass_name, const_name = const.split('::', 2) klass = Object.const_get(klass_name) klass.send(:remove_const, const_name) if klass.const_defined?(const_name) klass.const_set(const_name, value) end end def load_catalogue(type, exported = false, manifest_opts = {}) with_vardir do node_name = nodename(type) hiera_config_value = self.respond_to?(:hiera_config) ? hiera_config : nil hiera_data_value = self.respond_to?(:hiera_data) ? hiera_data : nil catalogue = build_catalog(node_name, facts_hash(node_name), trusted_facts_hash(node_name), hiera_config_value, build_code(type, manifest_opts), exported, node_params_hash, hiera_data_value) test_module = type == :host ? nil : class_name.split('::').first if type == :define RSpec::Puppet::Coverage.add_filter(class_name, title) else RSpec::Puppet::Coverage.add_filter(type.to_s, class_name) end RSpec::Puppet::Coverage.add_from_catalog(catalogue, test_module) catalogue end end def import_str import_str = "" adapter.modulepath.each { |d| if File.exists?(File.join(d, 'manifests', 'init.pp')) path_to_manifest = File.join([ d, 'manifests', class_name.split('::')[1..-1] ].flatten) import_str = [ "import '#{d}/manifests/init.pp'", "import '#{path_to_manifest}.pp'", '', ].join("\n") break elsif File.exists?(d) import_str = "import '#{adapter.manifest}'\n" break end } import_str end def site_pp_str site_pp_str = '' filepath = adapter.manifest if (!filepath.nil?) && File.file?(filepath) site_pp_str = File.open(filepath).read end site_pp_str end def test_manifest(type, opts = {}) opts[:params] = params if self.respond_to?(:params) if type == :class if opts[:params].nil? || opts[:params] == {} "include #{class_name}" else "class { '#{class_name}': #{param_str(opts[:params])} }" end elsif type == :application if opts.has_key?(:params) "site { #{class_name} { '#{title}': #{param_str(opts[:params])} } }" else raise ArgumentError, "You need to provide params for an application" end elsif type == :define title_str = if title.is_a?(Array) '[' + title.map { |r| "'#{r}'" }.join(', ') + ']' else "'#{title}'" end if opts.has_key?(:params) "#{class_name} { #{title_str}: #{param_str(opts[:params])} }" else "#{class_name} { #{title_str}: }" end elsif type == :host nil elsif type == :type_alias "$test = #{str_from_value(opts[:test_value])}\nassert_type(#{self.class.top_level_description}, $test)" end end def nodename(type) return node if self.respond_to?(:node) if [:class, :define, :function, :application].include? type Puppet[:certname] else class_name end end def class_name self.class.top_level_description.downcase end def pre_cond if self.respond_to?(:pre_condition) && !pre_condition.nil? if pre_condition.is_a? Array pre_condition.compact.join("\n") else pre_condition end else nil end end def post_cond if self.respond_to?(:post_condition) && !post_condition.nil? if post_condition.is_a? Array post_condition.compact.join("\n") else post_condition end else nil end end def facts_hash(node) base_facts = { 'clientversion' => Puppet::PUPPETVERSION, 'environment' => environment, } node_facts = { 'hostname' => node.split('.').first, 'fqdn' => node, 'domain' => node.split('.', 2).last, 'clientcert' => node, 'networking' => { 'fqdn' => node, 'domain' => node.split('.', 2).last, 'hostname' => node.split('.').first } } result_facts = if RSpec.configuration.default_facts.any? munge_facts(RSpec.configuration.default_facts) else {} end result_facts.merge!(munge_facts(base_facts)) result_facts.merge!(munge_facts(facts)) if self.respond_to?(:facts) result_facts.merge!(munge_facts(node_facts)) # Facter currently supports lower case facts. Bug FACT-777 has been submitted to support case sensitive # facts. downcase_facts = Hash[result_facts.map { |k, v| [k.downcase, v] }] downcase_facts end def node_params_hash params = RSpec.configuration.default_node_params if respond_to?(:node_params) params.merge(node_params) else params.dup end end def param_str(params) param_str_from_hash(params) end def trusted_facts_hash(node_name) return {} unless Puppet::Util::Package.versioncmp(Puppet.version, '4.3.0') >= 0 extensions = {} if RSpec.configuration.default_trusted_facts.any? extensions.merge!(RSpec.configuration.default_trusted_facts) end extensions.merge!(trusted_facts) if self.respond_to?(:trusted_facts) extensions end def str_from_value(value) case value when Hash kvs = value.collect do |k,v| "#{str_from_value(k)} => #{str_from_value(v)}" end.join(", ") "{ #{kvs} }" when Array vals = value.map do |v| str_from_value(v) end.join(", ") "[ #{vals} ]" when :default 'default' # verbatim default keyword when :undef 'undef' # verbatim undef keyword when Symbol str_from_value(value.to_s) else escape_special_chars(value.inspect) end end def param_str_from_hash(params_hash) # the param_str has special quoting rules, because the top-level keys are the Puppet # params, which may not be quoted params_hash.collect do |k,v| "#{k.to_s} => #{str_from_value(v)}" end.join(', ') end def setup_puppet vardir = Dir.mktmpdir Puppet[:vardir] = vardir # Enable app_management by default for Puppet versions that support it if Puppet::Util::Package.versioncmp(Puppet.version, '4.3.0') >= 0 && Puppet.version.to_i < 5 Puppet[:app_management] = true end adapter.modulepath.map do |d| Dir["#{d}/*/lib"].entries end.flatten.each do |lib| $LOAD_PATH << lib end vardir end def with_vardir begin vardir = setup_puppet return yield(vardir) if block_given? ensure FileUtils.rm_rf(vardir) if vardir && File.directory?(vardir) end end def build_catalog_without_cache(nodename, facts_val, trusted_facts_val, hiera_config_val, code, exported, node_params, *_) # If we're going to rebuild the catalog, we should clear the cached instance # of Hiera that Puppet is using. This opens the possibility of the catalog # now being rebuilt against a differently configured Hiera (i.e. :hiera_config # set differently in one example group vs. another). # It would be nice if Puppet offered a public API for invalidating their # cached instance of Hiera, but que sera sera. We will go directly against # the implementation out of absolute necessity. HieraPuppet.instance_variable_set('@hiera', nil) if defined? HieraPuppet Puppet[:code] = code stub_facts! facts_val node_facts = Puppet::Node::Facts.new(nodename, facts_val.dup) node_params = facts_val.merge(node_params) node_obj = Puppet::Node.new(nodename, { :parameters => node_params, :facts => node_facts }) if Puppet::Util::Package.versioncmp(Puppet.version, '4.3.0') >= 0 Puppet.push_context( { :trusted_information => Puppet::Context::TrustedInformation.new('remote', nodename, trusted_facts_val) }, "Context for spec trusted hash" ) end adapter.catalog(node_obj, exported) end def stub_facts!(facts) if facts['operatingsystem'] && facts['operatingsystem'].to_s.downcase == 'windows' Puppet::Util::Platform.pretend_to_be :windows else Puppet::Util::Platform.pretend_to_be :posix end Puppet.settings[:autosign] = false facts.each { |k, v| Facter.add(k) { setcode { v } } } end def build_catalog(*args) @@cache.get(*args) do |*args| build_catalog_without_cache(*args) end end def munge_facts(facts) return facts.reduce({}) do | memo, (k, v)| memo.tap { |m| m[k.to_s] = munge_facts(v) } end if facts.is_a? Hash return facts.reduce([]) do |memo, v| memo << munge_facts(v); memo end if facts.is_a? Array facts end def escape_special_chars(string) string.gsub!(/\$/, "\\$") string end def rspec_compatibility if RSpec::Version::STRING < '3' # RSpec 2 compatibility: alias_method :failure_message_for_should, :failure_message alias_method :failure_message_for_should_not, :failure_message_when_negated end end # Helper to return a resource/node reference, so it gets translated in params to a raw string # without quotes. # # @param [String] type reference type # @param [String] title reference title # @return [RSpec::Puppet::RawString] return a new RawString with the type/title populated correctly def ref(type, title) return RSpec::Puppet::RawString.new("#{type}['#{title}']") end # @!attribute [r] adapter # @api private # @return [Class < RSpec::Puppet::Adapters::Base] attr_accessor :adapter end end rspec-puppet-2.6.1/rspec-puppet.gemspec000066400000000000000000000007451312614575600201630ustar00rootroot00000000000000Gem::Specification.new do |s| s.name = 'rspec-puppet' s.version = '2.6.1' s.homepage = 'https://github.com/rodjek/rspec-puppet/' s.summary = 'RSpec tests for your Puppet manifests' s.description = 'RSpec tests for your Puppet manifests' s.license = 'MIT' s.executables = ['rspec-puppet-init'] s.files = Dir['CHANGELOG.md', 'LICENSE.md', 'README.md', 'lib/**/*', 'bin/**/*'] s.add_dependency 'rspec' s.authors = ['Tim Sharpe'] s.email = 'tim@sharpe.id.au' end rspec-puppet-2.6.1/spec/000077500000000000000000000000001312614575600151135ustar00rootroot00000000000000rspec-puppet-2.6.1/spec/applications/000077500000000000000000000000001312614575600176015ustar00rootroot00000000000000rspec-puppet-2.6.1/spec/applications/orch_app_spec.rb000066400000000000000000000011661312614575600227370ustar00rootroot00000000000000require 'spec_helper' describe 'orch_app', :if => Puppet::Util::Package.versioncmp(Puppet.version, '4.3.0') >= 0 do let(:node) { 'my_node' } let(:title) { 'my_awesome_app' } context 'with params' do let(:params) do { :nodes => { ref('Node', node) => ref('Orch_app::Db', title), }, :mystring => 'foobar', } end it { should compile } it { should contain_orch_app(title) } it { should contain_orch_app__db(title) } end context 'missing params' do it { expect { should compile }.to raise_error(ArgumentError, /provide params for an app/) } end end rspec-puppet-2.6.1/spec/cache_spec.rb000066400000000000000000000033231312614575600175160ustar00rootroot00000000000000require 'spec_helper' require 'rspec-puppet/cache' describe RSpec::Puppet::Cache do let(:compiler) { Hash.new } subject do described_class.new do |args| compiler[args] end end describe "fetching cached entries" do it "calls the get_proc on cache misses" do compiler["example.com"] = "New catalog!" fetched_obj = subject.get("example.com") expect(fetched_obj).to eq("New catalog!") end it "can supply a proc to the get method" do compiler["example.com"] = "New catalog!" fetched_obj = subject.get("example.com") do |args| compiler[args] + "!!" end expect(fetched_obj).to eq("New catalog!!!") end it "can handle procs with multiple args" do compiler["example.com"] = "New catalog!" fetched_obj = subject.get("example.com", " Yay!") do |arg1, arg2| compiler[arg1] + arg2 end expect(fetched_obj).to eq("New catalog! Yay!") end it "reuses cached entries" do compiler["example.com"] = "Cachable catalog!" first = subject.get("example.com") second = subject.get("example.com") expect(first.object_id).to eq(second.object_id) end it "evicts expired entries" do compiler["evicting.example.com"] = "Catalog to evict" 0.upto(15) do |i| compiler["node#{i}.example.com"] = "Catalog for node #{i}" end first = subject.get("evicting.example.com") 0.upto(15) do |i| subject.get("node#{i}.example.com") end compiler["evicting.example.com"] = "Replacement catalog" second = subject.get("evicting.example.com") expect(first).to eq("Catalog to evict") expect(second).to eq("Replacement catalog") end end end rspec-puppet-2.6.1/spec/classes/000077500000000000000000000000001312614575600165505ustar00rootroot00000000000000rspec-puppet-2.6.1/spec/classes/array_spec.rb000066400000000000000000000032121312614575600212230ustar00rootroot00000000000000require 'spec_helper' describe 'structured_data' do describe "with a single level array of strings" do let(:params) do {'data' => ['foo', 'bar', 'baz', 'quux']} end it { should contain_structured_data__def('thing').with( { 'data' => ['foo', 'bar', 'baz', 'quux'] } ) } end describe "with integers as data values" do let(:params) do { 'data' => ['first', 1, 'second', 2] } end it { should contain_structured_data__def('thing').with( { 'data' => ['first', 1, 'second', 2] } ) } end describe 'with nested arrays' do let(:params) do { 'data' => [ 'first', 'second', ['third', 'fourth'], 5, 6 ] } end # Puppet 2.6 will automatically flatten nested arrays. If we're going # to be testing recursive data structures, we might as well ensure that # we're still handling numeric values correctly. describe 'on Puppet 2.6', :if => Puppet.version =~ /^2\.6/ do it { should contain_structured_data__def('thing').with( { 'data' => [ 'first', 'second', 'third', 'fourth', 5, 6 ] } ) } end describe 'on Puppet 2.7 and later', :unless => Puppet.version =~ /^2\.6/ do it { should contain_structured_data__def('thing').with( { 'data' => [ 'first', 'second', ['third', 'fourth'], 5, 6 ] } ) } end end end rspec-puppet-2.6.1/spec/classes/boolean_regexp_spec.rb000066400000000000000000000006651312614575600231070ustar00rootroot00000000000000require 'spec_helper' describe 'boolean_test' do let(:title) { 'bool.testing' } let(:params) { { :bool => false } } let(:message_re) { /bool is false/ } it { should create_notify("bool testing").with_message(message_re) } # `should_not with_messsage` == `should without_message` it { should_not create_notify("bool testing").with_message(/true/) } it { should create_notify("bool testing").without_message(/true/) } end rspec-puppet-2.6.1/spec/classes/boolean_spec.rb000066400000000000000000000004351312614575600215300ustar00rootroot00000000000000require 'spec_helper' if Puppet::PUPPETVERSION !~ /0\.2/ describe 'boolean_test' do let(:title) { 'bool.testing' } let(:params) { { :bool => false } } it { should create_notify("bool testing")\ .with_message("This will print when \$bool is false.") } end end rspec-puppet-2.6.1/spec/classes/catalogue_cache_spec.rb000066400000000000000000000034301312614575600231760ustar00rootroot00000000000000require 'spec_helper' describe 'test::bare_class' do describe 'cache between adjacent examples' do catalogue_id = nil it 'records the initial catalogue ID' do catalogue_id = catalogue.object_id end it 'should contain the same catalogue ID' do expect(catalogue.object_id).to eq(catalogue_id) end end describe 'cache multiple catalogues' do catalogue_ids = {} (1..10).each do |i| context "iteration #{i}" do let(:facts) do { 'iteration' => i } end it 'records the initial catalogue ID' do catalogue_ids[i] = catalogue.object_id end end end (1..10).each do |i| context "iteration #{i}" do let(:facts) do { 'iteration' => i } end it 'should contain the same catalogue ID' do expect(catalogue.object_id).to eq(catalogue_ids[i]) end end end end describe 'limits number of cached catalogues' do catalogue_ids = {} (1..20).each do |i| context "iteration #{i}" do let(:facts) do { 'iteration' => i } end it 'records the initial catalogue ID' do catalogue_ids[i] = catalogue.object_id end end end (1..4).each do |i| context "iteration #{i}" do let(:facts) do { 'iteration' => i } end it 'should receive a new catalogue ID' do expect(catalogue.object_id).not_to eq(catalogue_ids[i]) end end end (9..20).each do |i| context "iteration #{i}" do let(:facts) do { 'iteration' => i } end it 'should contain the same catalogue ID' do expect(catalogue.object_id).to eq(catalogue_ids[i]) end end end end end rspec-puppet-2.6.1/spec/classes/cleanup_spec.rb000066400000000000000000000003741312614575600215420ustar00rootroot00000000000000require 'spec_helper' describe '#rspec_puppet_cleanup' do it { expect(respond_to?(:rspec_puppet_cleanup)).to be true } it 'should wipe @catalogue' do @catalogue = Object.new rspec_puppet_cleanup expect(@catalogue).to be_nil end end rspec-puppet-2.6.1/spec/classes/cycle_bad_spec.rb000066400000000000000000000001201312614575600220050ustar00rootroot00000000000000require 'spec_helper' describe 'cycle::bad' do it { should_not compile } end rspec-puppet-2.6.1/spec/classes/cycle_good_spec.rb000066400000000000000000000001751312614575600222210ustar00rootroot00000000000000require 'spec_helper' describe 'cycle::good' do it { should compile } it { should_not compile.and_raise_error(//) } end rspec-puppet-2.6.1/spec/classes/default_spec.rb000066400000000000000000000002511312614575600215310ustar00rootroot00000000000000require 'spec_helper' describe 'default_test', :if => Puppet.version.to_f >= 4.0 do let(:params) { { :value => :default } } it { should compile.with_all_deps } end rspec-puppet-2.6.1/spec/classes/escape_spec.rb000066400000000000000000000002451312614575600213500ustar00rootroot00000000000000require 'spec_helper' describe 'escape' do let(:params) { { :content => '$MSG foo' } } it { should contain_file('/tmp/escape').with_content(/\$MSG foo/) } end rspec-puppet-2.6.1/spec/classes/export_resource_spec.rb000066400000000000000000000016741312614575600233470ustar00rootroot00000000000000require 'spec_helper' describe 'export_resource' do describe 'exported_resources accessor' do it 'should support the contain_* matcher' do expect(exported_resources).to contain_file('/exported/resource')\ .with_content('Exported Content') end it 'should support the have_*_resource_count matcher' do expect(exported_resources).to have_file_resource_count(1) end end describe 'exported_resources sub-context' do subject { exported_resources } it 'should support the contain_* matcher' do should contain_file('/exported/resource')\ .with_content('Exported Content') end it 'should support the have_*_resource_count matcher' do should have_file_resource_count(1) end end describe 'normal catalogue tests' do it 'should not match exported resources' do should_not contain_file('/exported/resource') should have_file_resource_count(0) end end end rspec-puppet-2.6.1/spec/classes/facts_spec.rb000066400000000000000000000074361312614575600212210ustar00rootroot00000000000000require 'spec_helper' family = 'RedHat' # The current behavior is to convert a fact name to lower case. An issue, FACT-777, has been submitted as a bug # with the description of "Facter should not downcast fact names". The "mixed case in facts" tests this functionality. describe 'structured_facts::hash' do context 'symbols and strings in facts', :if => Puppet.version.to_f >= 4.0 do let(:facts) {{ :os => { 'family' => family } }} it { should contain_class('structured_facts::hash') } it { should compile.with_all_deps } it { should contain_notify(family) } end context 'only symbols in facts', :if => Puppet.version.to_f >= 4.0 do let(:facts) {{ :os => { :family => family } }} it { should contain_class('structured_facts::hash') } it { should compile.with_all_deps } it { should contain_notify(family) } end # See note concerning mixed case in facts at the beginning of the file context 'mixed case symbols in facts', :if => Puppet.version.to_f >= 4.0 do let(:facts) {{ :oS => { :family => family } }} it { should contain_class('structured_facts::hash') } it { should compile.with_all_deps } it { should contain_notify(family) } end context 'only strings in facts', :if => Puppet.version.to_f >= 4.0 do let(:facts) {{ 'os' => { 'family' => family } }} it { should contain_class('structured_facts::hash') } it { should compile.with_all_deps } it { should contain_notify(family) } end # See note concerning mixed case in facts at the beginning of the file context 'mixed case strings in facts', :if => Puppet.version.to_f >= 4.0 do let(:facts) {{ 'oS' => { 'family' => family } }} it { should contain_class('structured_facts::hash') } it { should compile.with_all_deps } it { should contain_notify(family) } end end describe 'structured_facts::top_scope' do context 'symbols and strings in facts' do let(:facts) {{ :os => { 'family' => family } }} it { should contain_class('structured_facts::top_scope') } it { should compile.with_all_deps } it { should contain_notify(family) } end context 'only symbols in facts' do let(:facts) {{ :os => { :family => family } }} it { should contain_class('structured_facts::top_scope') } it { should compile.with_all_deps } it { should contain_notify(family) } end # See note concerning mixed case in facts at the beginning of the file context 'mixed case in facts' do let(:facts) {{ :Os => { :family => family } }} it { should contain_class('structured_facts::top_scope') } it { should compile.with_all_deps } it { should contain_notify(family) } end context 'only string in facts' do let(:facts) {{ 'os' => { 'family' => family } }} it { should contain_class('structured_facts::top_scope') } it { should compile.with_all_deps } it { should contain_notify(family) } end # See note concerning mixed case in facts at the beginning of the file context 'mixed case in facts' do let(:facts) {{ 'Os' => { 'family' => family } }} it { should contain_class('structured_facts::top_scope') } it { should compile.with_all_deps } it { should contain_notify(family) } end end describe 'structured_facts::case_check' do context 'mixed case in structure fact nested keys', :if => Puppet.version.to_f >= 4.0 do let(:facts) {{ 'custom_fact' => { 'MixedCase' => 'value' } }} it { should contain_class('structured_facts::case_check') } it { should compile.with_all_deps } it { should contain_notify('value') } end end rspec-puppet-2.6.1/spec/classes/hash_spec.rb000066400000000000000000000033571312614575600210420ustar00rootroot00000000000000require 'spec_helper' describe 'structured_data' do describe "with a single level hash of strings" do let(:params) do {'data' => {'foo' => 'bar', 'baz' => 'quux'}} end it { should contain_structured_data__def('thing').with( {'data' => {'foo' => 'bar', 'baz' => 'quux'}} ) } end describe "with integers as keys" do let(:params) do { 'data' => {1 => 'uno', 2 => 'dos'}} end context "puppet less than 4", :unless => Puppet.version.to_f >= 4.0 do it { should contain_structured_data__def('thing').with( { 'data' => {"1" => 'uno', "2" => 'dos'}} ) } end context "puppet 4 or greater", :if => Puppet.version.to_f >= 4.0 do it { should contain_structured_data__def('thing').with( { 'data' => {1 => 'uno', 2 => 'dos'}} ) } end end describe 'with integers as values' do let(:params) do { 'data' => {'first' => 1, 'second' => 2}} end it { should contain_structured_data__def('thing').with( { 'data' => {'first' => 1, 'second' => 2}} ) } end describe 'with nested hashes' do # the key "sec.ond" needs quoting, otherwise it would be a syntax error in the manifest let(:params) do { 'data' => { 'first' => 1, 'sec.ond' => 2, 'third' => { 'alpha' => 'a', 'beta' => 'b', } } } end it { should contain_structured_data__def('thing').with( { 'data' => { 'first' => 1, 'sec.ond' => 2, 'third' => { 'alpha' => 'a', 'beta' => 'b', } } } ) } end end rspec-puppet-2.6.1/spec/classes/hiera_integration_spec.rb000066400000000000000000000005451312614575600236060ustar00rootroot00000000000000require 'spec_helper' # hiera is not supported before 2.7 describe 'test::hiera', :if => Puppet.version.to_f >= 3.0 do context 'with :hiera_config set' do let(:hiera_config) { 'spec/fixtures/hiera.yaml' } it { should contain_notify('foo') } end context 'without :hiera_config set' do it { should contain_notify('not found') } end end rspec-puppet-2.6.1/spec/classes/node_params_spec.rb000066400000000000000000000016171312614575600224040ustar00rootroot00000000000000require 'spec_helper' describe 'node_params', :if => Puppet::Util::Package.versioncmp(Puppet.version, '3.0.0') >= 0 do fuzzed = { :string => 'foo bar baz', :hash => { 'foo' => 'bar', 'baz' => 'foo' }, :array => %w[baz foo bar], :true => true, :false => false, :integer => 5, :float => 4.4, :nil => nil } let(:node_params) { fuzzed } it 'compiles into a catalogue without dependency cycles' do is_expected.to compile.with_all_deps is_expected.to contain_class('node_params') end fuzzed.each do |title, message| it "contains Notify[#{title}] with message => #{message}" do is_expected.to contain_notify(title.to_s).with(:message => message) end end it "doesn't leak to the facts hash", :if => Puppet::Util::Package.versioncmp(Puppet.version, '4.0.0') >= 0 do is_expected.to contain_notify('stringfact').with(:message => '') end end rspec-puppet-2.6.1/spec/classes/relationship__before_spec.rb000066400000000000000000000045101312614575600242710ustar00rootroot00000000000000require 'spec_helper' describe 'relationships::before' do let(:facts) { {:operatingsystem => 'debian'} } it { should contain_notify('foo').that_comes_before('Notify[bar]') } it { should contain_notify('foo').that_comes_before('Notify[baz]') } it { should contain_notify('bar').that_comes_before('Notify[baz]') } it { should contain_notify('bar').that_requires('Notify[foo]') } it { should contain_notify('baz').that_requires('Notify[foo]') } it { should contain_notify('baz').that_requires('Notify[bar]') } it { should contain_notify('foo').that_comes_before(['Notify[bar]','Notify[baz]']) } it { should contain_notify('bar').that_comes_before(['Notify[baz]']) } it { should contain_notify('bar').that_requires(['Notify[foo]']) } it { should contain_notify('baz').that_requires(['Notify[foo]','Notify[bar]']) } it { should contain_class('relationship::before::pre').that_comes_before('Class[relationship::before::post]') } it { should contain_class('relationship::before::post').that_requires('Class[relationship::before::pre]') } it { should contain_notify('pre').that_comes_before(['Notify[post]']) } it { should contain_notify('post').that_requires(['Notify[pre]']) } it { should contain_file('/tmp/foo').that_comes_before(['File[/tmp/foo/bar]']) } it { should contain_file('/tmp/foo/bar').that_requires(['File[/tmp/foo]']) } it { should contain_notify('bazz').that_comes_before(['File[/tmp/foo/bar]']) } it { should contain_notify('qux').that_requires(['File[/tmp/foo]']) } it { should contain_notify('bazz').that_comes_before(['Notify[qux]']) } it { should contain_notify('qux').that_requires(['Notify[bazz]']) } it { should_not contain_notify('foo').that_comes_before('Notify[unknown]') } it { should_not contain_notify('bar').that_comes_before('Notify[unknown]') } it { should_not contain_notify('baz').that_comes_before('Notify[unknown]') } it { should_not contain_notify('foo').that_requires('Notify[unknown]') } it { should_not contain_notify('bar').that_requires('Notify[unknown]') } it { should_not contain_notify('baz').that_requires('Notify[unknown]') } it { should_not contain_class('relationship::before::pre').that_comes_before('Class[relationship::before::unknown]') } it { should_not contain_class('relationship::before::post').that_requires('Class[relationship::before::unknown]') } end rspec-puppet-2.6.1/spec/classes/relationship__notify_spec.rb000066400000000000000000000016671312614575600243510ustar00rootroot00000000000000require 'spec_helper' describe 'relationships::notify' do it { should contain_notify('foo').that_notifies('Notify[bar]') } it { should contain_notify('baz').that_notifies('Notify[bar]') } it { should contain_notify('baz').that_notifies('Notify[gronk]') } it { should contain_notify('gronk').that_subscribes_to('Notify[baz]') } it { should contain_notify('bar').that_subscribes_to('Notify[baz]') } it { should contain_notify('bar').that_subscribes_to('Notify[foo]') } it { should contain_notify('foo').that_notifies(['Notify[bar]']) } it { should contain_notify('baz').that_notifies(['Notify[bar]','Notify[gronk]']) } it { should contain_notify('gronk').that_subscribes_to(['Notify[baz]']) } it { should contain_notify('bar').that_subscribes_to(['Notify[baz]','Notify[foo]']) } it { should contain_notify('pre').that_notifies(['Notify[post]']) } it { should contain_notify('post').that_subscribes_to(['Notify[pre]']) } end rspec-puppet-2.6.1/spec/classes/relationship__titles_spec.rb000066400000000000000000000011261312614575600243330ustar00rootroot00000000000000require 'spec_helper' describe 'relationships::titles' do let(:facts) { {:operatingsystem => 'Debian', :kernel => 'Linux'} } it { should compile } it { should compile.with_all_deps } it { should contain_file('/etc/svc') } it { should contain_service('svc-title') } it { should contain_file('/etc/svc').that_notifies('Service[svc-name]') } it { should contain_file('/etc/svc').that_comes_before('Service[svc-name]') } it { should contain_service('svc-title').that_requires('File[/etc/svc]') } it { should contain_service('svc-title').that_subscribes_to('File[/etc/svc]') } end rspec-puppet-2.6.1/spec/classes/relationships_complex_spec.rb000066400000000000000000000002301312614575600245150ustar00rootroot00000000000000require 'spec_helper' describe 'relationships::complex' do it { should contain_notify('foo').that_comes_before(['Notify[baz]', 'Notify[bar]']) } end rspec-puppet-2.6.1/spec/classes/sysctl_common_spec.rb000066400000000000000000000063271312614575600230100ustar00rootroot00000000000000require 'spec_helper' describe 'sysctl::common' do it { should contain_exec('sysctl/reload') \ .with_command('/sbin/sysctl -p /etc/sysctl.conf').with_returns([0, 2]) } it { should_not create_augeas('foo') } describe 'when using with to specify a hash of parameters' do it 'should fail if the parameter is not contained in the resource' do expect do expect(subject).to contain_exec('sysctl/reload').with('foo' => 'bar') end.to raise_error(RSpec::Expectations::ExpectationNotMetError) end it 'should pass if the parameters are contained in the resource' do expect(subject).to contain_exec('sysctl/reload').with( 'refreshonly' => 'true', 'returns' => [0, 2] ) end end describe 'when using without to specify parameter name(s)' do it 'should pass if the parameter name is not contained in the resource' do expect(subject).to contain_exec('sysctl/reload').without('foo') end it 'should pass if the parameter names are not contained in the resource' do expect(subject).to contain_exec('sysctl/reload').without(['foo', 'bar']) end it 'should fail if any of the parameter names are contained in the resource' do expect do expect(subject).to contain_exec('sysctl/reload').without(['foo', 'returns']) end.to raise_error(RSpec::Expectations::ExpectationNotMetError) end end describe 'when using without to specify parameter value(s)' do it 'should pass if the parameter value is not contained in the resource' do expect(subject).to contain_exec('sysctl/reload').without_refreshonly('false') end it 'should fail if the parameter value is contained in the resource' do expect do expect(subject).to contain_exec('sysctl/reload').without_refreshonly('true') end.to raise_error(RSpec::Expectations::ExpectationNotMetError) end end end describe 'sysctl::common' do let(:params) { { :test_param => "yes" } } it { should create_class("sysctl::common")\ .with_test_param("yes") } it { should have_class_count(1) } it { should have_exec_resource_count(1) } it { should have_resource_count(2) } it { should contain_notify('test') } end describe 'sysctl::common' do it { should contain_exec('sysctl/reload').only_with( :command => '/sbin/sysctl -p /etc/sysctl.conf', :refreshonly => true, :returns => [0, 2] )} it { should contain_exec('sysctl/reload') \ .only_with_command('/sbin/sysctl -p /etc/sysctl.conf') \ .only_with_refreshonly(true) \ .only_with_returns([0, 2]) } it 'should fail if not enough parameters are contained in the resource' do expect do expect(subject).to contain_exec('sysctl/reload').only_with( :command => '/sbin/sysctl -p /etc/sysctl.conf', :returns => [0, 2] ) end.to raise_error(RSpec::Expectations::ExpectationNotMetError) end it 'should fail if different parameters are contained in the resource' do expect do expect(subject).to contain_exec('sysctl/reload').only_with( :command => '/sbin/sysctl -p /etc/sysctl.conf', :refreshonly => true, :creates => '/tmp/bla' ) end.to raise_error(RSpec::Expectations::ExpectationNotMetError) end end rspec-puppet-2.6.1/spec/classes/test_api_spec.rb000066400000000000000000000022421312614575600217170ustar00rootroot00000000000000require 'spec_helper' describe 'test::bare_class' do describe 'rspec group' do it 'should have a catalogue method' do expect(catalogue).to be_a(Puppet::Resource::Catalog) end it 'subject should return a catalogue' do expect(subject.call).to be_a(Puppet::Resource::Catalog) end describe 'derivative group' do subject { catalogue.resource('Notify', 'foo') } it 'can redefine subject' do expect(subject).to be_a(Puppet::Resource) end end end describe 'coverage' do it 'class should be included in the coverage filter' do expect(RSpec::Puppet::Coverage.filters).to include('Class[Test::Bare_class]') end # file and line information was only added to resources created with # ensure_resource() in 4.6.0 (PUP-6530). if Puppet::Util::Package.versioncmp(Puppet.version, '4.6.0') >= 0 it 'should not include resources from other modules created with create_resources()' do expect(RSpec::Puppet::Coverage.instance.results[:resources]).to_not include('Notify[create_resources notify]') expect(subject).to contain_notify('create_resources notify') end end end end rspec-puppet-2.6.1/spec/classes/test_basic_spec.rb000066400000000000000000000006761312614575600222400ustar00rootroot00000000000000require 'spec_helper' describe 'test::basic' do it { should contain_fake('foo').with_three([{'foo' => 'bar'}]) } context 'testing node based facts' do let(:pre_condition) { 'notify { $::fqdn: }' } let(:node) { 'test123.test.com' } let(:facts) do { :fqdn => 'notthis.test.com', } end it { should contain_notify('test123.test.com') } it { should_not contain_notify('notthis.test.com') } end end rspec-puppet-2.6.1/spec/classes/test_classes_used_spec.rb000066400000000000000000000011431312614575600236220ustar00rootroot00000000000000require 'spec_helper' describe 'test::classes_used' do it { expect(RSpec).to receive(:deprecate).with(:include_class, {:replacement => :contain_class}) should include_class('test::bare_class') } it { expect(RSpec).to receive(:deprecate).with(:include_class, {:replacement => :contain_class}) should include_class('test::parameterised_class') } it { should contain_class('test::parameterised_class').with_text('bar') } it { should contain_class('test::bare_class') } it { should contain_class('test::parameterised_class').with_something(Proc.new { |v| v.nil? || v.empty? }) } end rspec-puppet-2.6.1/spec/classes/test_compile_error_spec.rb000066400000000000000000000003241312614575600240060ustar00rootroot00000000000000require 'spec_helper' describe 'test::compile_error' do it 'should provide a useful message when compilation fails' do should compile.with_all_deps.and_raise_error(/Parameter managehome failed/) end end rspec-puppet-2.6.1/spec/classes/test_duplicate_alias_spec.rb000066400000000000000000000003411312614575600242670ustar00rootroot00000000000000require 'spec_helper' describe 'test::duplicate_alias' do it { should compile } it { should contain_exec('foo_bar_1') } it { should contain_exec('foo_bar_2') } it { should_not contain_exec('/bin/echo foo bar') } end rspec-puppet-2.6.1/spec/classes/test_fail_spec.rb000066400000000000000000000001441312614575600220600ustar00rootroot00000000000000require 'spec_helper' describe 'test::fail' do it { should compile.and_raise_error(/test/) } end rspec-puppet-2.6.1/spec/classes/test_provider_suitability_spec.rb000066400000000000000000000010741312614575600254240ustar00rootroot00000000000000require 'spec_helper' describe 'test::provider_suitability' do [ { :operatingsystem => 'Darwin', :osfamily => 'Darwin', :kernel => 'Darwin', }, { :operatingsystem => 'CentOS', :osfamily => 'RedHat', :kernel => 'Linux', }, { :operatingsystem => 'Solaris', :osfamily => 'Solaris', :kernel => 'SunOS', }, ].each do |f| context "On #{f[:operatingsystem]}" do let(:facts) { f } it { should compile.with_all_deps } it { should contain_user('testuser') } end end end rspec-puppet-2.6.1/spec/classes/test_user_spec.rb000066400000000000000000000002341312614575600221230ustar00rootroot00000000000000require 'spec_helper' describe 'test::user' do it { should contain_user('luke').only_with({ 'ensure' => 'present', 'uid' => '501', }) } end rspec-puppet-2.6.1/spec/classes/test_windows_spec.rb000066400000000000000000000002211312614575600226330ustar00rootroot00000000000000require 'spec_helper' describe 'test::windows' do let(:facts) { {:operatingsystem => 'windows' } } it { should compile.with_all_deps } end rspec-puppet-2.6.1/spec/classes/trusted_facts_spec.rb000066400000000000000000000040761312614575600227700ustar00rootroot00000000000000require 'spec_helper' describe 'trusted_facts', :if => Puppet::Util::Package.versioncmp(Puppet.version, '4.3.0') >= 0 do context 'without node set' do it { should contain_class('trusted_facts') } it { should compile.with_all_deps } it { should contain_notify("certname-my_node.my_node") } it { should contain_notify("authenticated-remote") } it { should contain_notify("hostname-my_node") } it { should contain_notify("domain-my_node") } it { should contain_notify("no-extensions") } end context 'FQDN as certname' do let(:node) { 'trusted.example.com' } it { should contain_class('trusted_facts') } it { should compile.with_all_deps } it { should contain_notify("certname-#{node}") } it { should contain_notify("authenticated-remote") } it { should contain_notify("hostname-trusted") } it { should contain_notify("domain-example.com") } it { should contain_notify("no-extensions") } end context 'shortname as certname' do let(:node) { 'trusted' } it { should contain_class('trusted_facts') } it { should compile.with_all_deps } it { should contain_notify("certname-#{node}") } it { should contain_notify("authenticated-remote") } it { should contain_notify("hostname-trusted") } it { should contain_notify("domain-") } it { should contain_notify("no-extensions") } end context 'with extensions' do extensions = { 'pp_uuid' => 'ED803750-E3C7-44F5-BB08-41A04433FE2E', '1.3.6.1.4.1.34380.1.2.1' => 'ssl-termination' } let(:trusted_facts) { extensions } let(:node) { 'trusted.example.com' } it { should contain_class('trusted_facts') } it { should compile.with_all_deps } it { should contain_notify("certname-#{node}") } it { should contain_notify("authenticated-remote") } it { should contain_notify("hostname-trusted") } it { should contain_notify("domain-example.com") } it { should_not contain_notify("no-extensions") } extensions.each do |k,v| it { should contain_notify("extension-#{k}-#{v}") } end end end rspec-puppet-2.6.1/spec/classes/undef_spec.rb000066400000000000000000000030151312614575600212070ustar00rootroot00000000000000require 'spec_helper' describe 'undef_test' do context "with required_attribute => 'some_string'" do context 'and defaults_to_undef unspecified' do let(:params) { { :required_attribute => 'some_string' } } it { should compile.with_all_deps } it { should contain_class('undef_test').with(:required_attribute => 'some_string') } it { should contain_class('undef_test').without_defaults_to_undef } end context 'and defaults_to_undef => :undef' do let(:params) { { :required_attribute => 'some_string', :defaults_to_undef => :undef } } it { should compile.with_all_deps } it { should contain_class('undef_test').with(:required_attribute => 'some_string') } it { should contain_class('undef_test').without_defaults_to_undef } end end context "with required_attribute => :undef", :unless => Puppet.version =~ /^2/ do context 'and defaults_to_undef unspecified' do let(:params) { { :required_attribute => :undef } } it { should compile.with_all_deps } it { should contain_class('undef_test').without_required_attribute } it { should contain_class('undef_test').without_defaults_to_undef } end context 'and defaults_to_undef => :undef' do let(:params) { { :required_attribute => :undef, :defaults_to_undef => :undef } } it { should compile.with_all_deps } it { should contain_class('undef_test').without_required_attribute } it { should contain_class('undef_test').without_defaults_to_undef } end end end rspec-puppet-2.6.1/spec/defines/000077500000000000000000000000001312614575600165305ustar00rootroot00000000000000rspec-puppet-2.6.1/spec/defines/cleanup_spec.rb000066400000000000000000000003741312614575600215220ustar00rootroot00000000000000require 'spec_helper' describe '#rspec_puppet_cleanup' do it { expect(respond_to?(:rspec_puppet_cleanup)).to be true } it 'should wipe @catalogue' do @catalogue = Object.new rspec_puppet_cleanup expect(@catalogue).to be_nil end end rspec-puppet-2.6.1/spec/defines/escape_def_spec.rb000066400000000000000000000003021312614575600221400ustar00rootroot00000000000000require 'spec_helper' describe 'escape::def' do let(:title) { '/tmp/bla' } let(:params) { {:content => 'bar $BLA'} } it { should contain_file('/tmp/bla').with_content(/bar \$BLA/) } end rspec-puppet-2.6.1/spec/defines/sysctl_before_spec.rb000066400000000000000000000013531312614575600227340ustar00rootroot00000000000000require 'spec_helper' describe 'sysctl::before' do let(:title) { 'sysctl::before' } let(:params) { { :value => "title" } } it "Should raise an error about needing the sysctl::common class" do expect { should create_notify("message-title")\ .with_message("This should print if the class is here first.") }\ .to raise_error(Puppet::Error, /Could not find resource 'Class\[Sysctl::Common\]/) end end describe 'sysctl::before' do let(:title) { 'test define' } let(:pre_condition) { [ '# we need sysctl common', 'class {"sysctl::common":}' ] } let(:params) { { :value => "title" } } it { should create_sysctl__before('test define').with_value("title") } it { should contain_class("sysctl::common") } end rspec-puppet-2.6.1/spec/defines/sysctl_spec.rb000066400000000000000000000011221312614575600214040ustar00rootroot00000000000000require 'spec_helper' nodoublequotes = Proc.new do |x| not x =~ /"/ end describe 'sysctl' do let(:title) { 'vm.swappiness' } let(:params) { {:value => '60'} } let(:pre_condition) { } it { should contain_class('sysctl::common') } it { should create_augeas('sysctl/vm.swappiness') \ .with_context('/files/etc/sysctl.conf') \ .with_changes("set vm.swappiness '60'") \ .with_changes(nodoublequotes) \ .with_onlyif("match vm.swappiness[.='60'] size == 0") \ .with_notify('Exec[sysctl/reload]')\ .without_foo } it { should have_sysctl_resource_count(1) } end rspec-puppet-2.6.1/spec/defines/test_addition_spec.rb000066400000000000000000000003201312614575600227140ustar00rootroot00000000000000require 'spec_helper' describe 'test::addition' do let(:title) { 'testtitle' } context 'when passing an integer' do let(:params) { {:value => 60} } it { should contain_notify('61') } end end rspec-puppet-2.6.1/spec/defines/test_api_spec.rb000066400000000000000000000010151312614575600216740ustar00rootroot00000000000000require 'spec_helper' describe 'sysctl' do let(:title) { 'vm.swappiness' } let(:params) { {:value => '60'} } describe 'rspec group' do it 'should have a catalogue method' do expect(catalogue).to be_a(Puppet::Resource::Catalog) end it 'subject should return a catalogue' do expect(subject.call).to be_a(Puppet::Resource::Catalog) end it 'should be included in the coverage filter' do expect(RSpec::Puppet::Coverage.filters).to include('Sysctl[vm.swappiness]') end end end rspec-puppet-2.6.1/spec/defines/test_loop_define_spec.rb000066400000000000000000000006071312614575600234140ustar00rootroot00000000000000require 'spec_helper' describe 'test::loop_define' do context 'with an array of plain strings' do let(:title) { ['a', 'b'] } context 'both sub resources in the catalogue' do it { should contain_package('a') } it { should contain_package('b') } end end context 'with a title containing a $' do let(:title) { '$test' } it { should compile } end end rspec-puppet-2.6.1/spec/defines/undef_def_spec.rb000066400000000000000000000032571312614575600220150ustar00rootroot00000000000000require 'spec_helper' describe 'undef_test::def' do let(:title) { 'some_undef_test' } context "with required_attribute => 'some_string'" do context 'and defaults_to_undef unspecified' do let(:params) { { :required_attribute => 'some_string' } } it { should compile.with_all_deps } it { should contain_undef_test__def('some_undef_test').with(:required_attribute => 'some_string') } it { should contain_undef_test__def('some_undef_test').without_defaults_to_undef } end context 'and defaults_to_undef => :undef' do let(:params) { { :required_attribute => 'some_string', :defaults_to_undef => :undef } } it { should compile.with_all_deps } it { should contain_undef_test__def('some_undef_test').with(:required_attribute => 'some_string') } it { should contain_undef_test__def('some_undef_test').without_defaults_to_undef } end end context "with required_attribute => :undef", :unless => Puppet.version =~ /^2/ do context 'and defaults_to_undef unspecified' do let(:params) { { :required_attribute => :undef } } it { should compile.with_all_deps } it { should contain_undef_test__def('some_undef_test').without_required_attribute } it { should contain_undef_test__def('some_undef_test').without_defaults_to_undef } end context 'and defaults_to_undef => :undef' do let(:params) { { :required_attribute => :undef, :defaults_to_undef => :undef } } it { should compile.with_all_deps } it { should contain_undef_test__def('some_undef_test').without_required_attribute } it { should contain_undef_test__def('some_undef_test').without_defaults_to_undef } end end end rspec-puppet-2.6.1/spec/fixtures/000077500000000000000000000000001312614575600167645ustar00rootroot00000000000000rspec-puppet-2.6.1/spec/fixtures/hiera.yaml000066400000000000000000000001321312614575600207340ustar00rootroot00000000000000--- :backends: - yaml :yaml: :datadir: spec/fixtures/hieradata :hierarchy: - common rspec-puppet-2.6.1/spec/fixtures/hieradata/000077500000000000000000000000001312614575600207065ustar00rootroot00000000000000rspec-puppet-2.6.1/spec/fixtures/hieradata/common.yaml000066400000000000000000000000161312614575600230570ustar00rootroot00000000000000--- data: foo rspec-puppet-2.6.1/spec/fixtures/manifests/000077500000000000000000000000001312614575600207555ustar00rootroot00000000000000rspec-puppet-2.6.1/spec/fixtures/manifests/site.pp000066400000000000000000000013761312614575600222710ustar00rootroot00000000000000node default { notify { 'test': } } node 'testhost_a' { file { '/tmp/a': } } node /testhost/ { include sysctl::common } node 'good_dep_host' { file { 'tmpdir': alias => '/tmp', path => '/tmp', } file { '/tmp/deptest1': require => File['tmpdir'], } file { '/tmp/deptest2': require => File['/tmp'], } } node 'facts.acme.com' { file { 'environment': path => $environment } if $::environment == 'test_env' { file { 'conditional_file': path => 'ignored' } } file { 'clientversion': path => $clientversion } file { 'fqdn': path => $fqdn } file { 'hostname': path => $hostname } file { 'domain': path => $domain } file { 'clientcert': path => "cert ${clientcert}" } } rspec-puppet-2.6.1/spec/fixtures/modules/000077500000000000000000000000001312614575600204345ustar00rootroot00000000000000rspec-puppet-2.6.1/spec/fixtures/modules/aliases/000077500000000000000000000000001312614575600220555ustar00rootroot00000000000000rspec-puppet-2.6.1/spec/fixtures/modules/aliases/types/000077500000000000000000000000001312614575600232215ustar00rootroot00000000000000rspec-puppet-2.6.1/spec/fixtures/modules/aliases/types/onlyarray.pp000066400000000000000000000000401312614575600255740ustar00rootroot00000000000000type Aliases::OnlyArray = Array rspec-puppet-2.6.1/spec/fixtures/modules/aliases/types/onlyhash.pp000066400000000000000000000000361312614575600254060ustar00rootroot00000000000000type Aliases::OnlyHash = Hash rspec-puppet-2.6.1/spec/fixtures/modules/aliases/types/shape.pp000066400000000000000000000000571312614575600246640ustar00rootroot00000000000000type Aliases::Shape = Enum['square', 'circle'] rspec-puppet-2.6.1/spec/fixtures/modules/boolean_test/000077500000000000000000000000001312614575600231125ustar00rootroot00000000000000rspec-puppet-2.6.1/spec/fixtures/modules/boolean_test/manifests/000077500000000000000000000000001312614575600251035ustar00rootroot00000000000000rspec-puppet-2.6.1/spec/fixtures/modules/boolean_test/manifests/init.pp000066400000000000000000000003251312614575600264070ustar00rootroot00000000000000class boolean_test($bool) { $real_bool = $bool ? { true => false, false => true, } if ($real_bool) { notify {"bool testing": message => "This will print when \$bool is false." } } } rspec-puppet-2.6.1/spec/fixtures/modules/cycle/000077500000000000000000000000001312614575600215335ustar00rootroot00000000000000rspec-puppet-2.6.1/spec/fixtures/modules/cycle/manifests/000077500000000000000000000000001312614575600235245ustar00rootroot00000000000000rspec-puppet-2.6.1/spec/fixtures/modules/cycle/manifests/bad.pp000066400000000000000000000001721312614575600246130ustar00rootroot00000000000000class cycle::bad { notify { 'foo': require => Notify['bar']; 'bar': require => Notify['foo']; } } rspec-puppet-2.6.1/spec/fixtures/modules/cycle/manifests/good.pp000066400000000000000000000001351312614575600250140ustar00rootroot00000000000000class cycle::good { notify { 'foo': require => Notify['bar']; 'bar': ; } } rspec-puppet-2.6.1/spec/fixtures/modules/cycle/manifests/init.pp000066400000000000000000000000001312614575600250160ustar00rootroot00000000000000rspec-puppet-2.6.1/spec/fixtures/modules/default_test/000077500000000000000000000000001312614575600231175ustar00rootroot00000000000000rspec-puppet-2.6.1/spec/fixtures/modules/default_test/manifests/000077500000000000000000000000001312614575600251105ustar00rootroot00000000000000rspec-puppet-2.6.1/spec/fixtures/modules/default_test/manifests/init.pp000066400000000000000000000000771312614575600264200ustar00rootroot00000000000000class default_test(Default $value) { notify { 'success': } } rspec-puppet-2.6.1/spec/fixtures/modules/dynamic/000077500000000000000000000000001312614575600220605ustar00rootroot00000000000000rspec-puppet-2.6.1/spec/fixtures/modules/dynamic/manifests/000077500000000000000000000000001312614575600240515ustar00rootroot00000000000000rspec-puppet-2.6.1/spec/fixtures/modules/dynamic/manifests/create_resources.pp000066400000000000000000000001441312614575600277460ustar00rootroot00000000000000class dynamic::create_resources { create_resources('notify', {'create_resources notify' => {}}) } rspec-puppet-2.6.1/spec/fixtures/modules/escape/000077500000000000000000000000001312614575600216745ustar00rootroot00000000000000rspec-puppet-2.6.1/spec/fixtures/modules/escape/manifests/000077500000000000000000000000001312614575600236655ustar00rootroot00000000000000rspec-puppet-2.6.1/spec/fixtures/modules/escape/manifests/def.pp000066400000000000000000000001511312614575600247610ustar00rootroot00000000000000define escape::def($content = '') { file { $title : ensure => file, content => $content } } rspec-puppet-2.6.1/spec/fixtures/modules/escape/manifests/init.pp000066400000000000000000000001501312614575600251650ustar00rootroot00000000000000class escape($content = '') { file { '/tmp/escape': ensure => file, content => $content } } rspec-puppet-2.6.1/spec/fixtures/modules/export_resource/000077500000000000000000000000001312614575600236645ustar00rootroot00000000000000rspec-puppet-2.6.1/spec/fixtures/modules/export_resource/manifests/000077500000000000000000000000001312614575600256555ustar00rootroot00000000000000rspec-puppet-2.6.1/spec/fixtures/modules/export_resource/manifests/init.pp000066400000000000000000000001401312614575600271540ustar00rootroot00000000000000class export_resource { @@file {'/exported/resource': content => 'Exported Content' } } rspec-puppet-2.6.1/spec/fixtures/modules/fake_type/000077500000000000000000000000001312614575600224035ustar00rootroot00000000000000rspec-puppet-2.6.1/spec/fixtures/modules/fake_type/lib/000077500000000000000000000000001312614575600231515ustar00rootroot00000000000000rspec-puppet-2.6.1/spec/fixtures/modules/fake_type/lib/puppet/000077500000000000000000000000001312614575600244665ustar00rootroot00000000000000rspec-puppet-2.6.1/spec/fixtures/modules/fake_type/lib/puppet/provider/000077500000000000000000000000001312614575600263205ustar00rootroot00000000000000rspec-puppet-2.6.1/spec/fixtures/modules/fake_type/lib/puppet/provider/fake/000077500000000000000000000000001312614575600272265ustar00rootroot00000000000000rspec-puppet-2.6.1/spec/fixtures/modules/fake_type/lib/puppet/provider/fake/default.rb000066400000000000000000000000631312614575600311760ustar00rootroot00000000000000Puppet::Type.type(:fake).provide(:default) do end rspec-puppet-2.6.1/spec/fixtures/modules/fake_type/lib/puppet/type/000077500000000000000000000000001312614575600254475ustar00rootroot00000000000000rspec-puppet-2.6.1/spec/fixtures/modules/fake_type/lib/puppet/type/fake.rb000066400000000000000000000005041312614575600267010ustar00rootroot00000000000000Puppet::Type.newtype(:fake) do feature :eleven, "11" feature :twelve, "12" newparam(:name, :isnamevar => true) newparam(:three) newparam(:four) do newvalues(/(one|two)/) end newproperty(:seven) newproperty(:eight) validate do fail('three is a required param') unless self[:three] end end rspec-puppet-2.6.1/spec/fixtures/modules/node_params/000077500000000000000000000000001312614575600227245ustar00rootroot00000000000000rspec-puppet-2.6.1/spec/fixtures/modules/node_params/manifests/000077500000000000000000000000001312614575600247155ustar00rootroot00000000000000rspec-puppet-2.6.1/spec/fixtures/modules/node_params/manifests/init.pp000066400000000000000000000010601312614575600262160ustar00rootroot00000000000000class node_params { notify { 'string': message => $::string, } if $facts { # protect against puppet 3 not having $facts hash notify { 'stringfact': message => "${facts['string']}", } } notify { 'hash': message => $::hash, } notify { 'array': message => $::array, } notify { 'true': message => $::true, } notify { 'false': message => $::false, } notify { 'integer': message => $::integer, } notify { 'float': message => $::float, } notify { 'nil': message => $::nil, } } rspec-puppet-2.6.1/spec/fixtures/modules/orch_app/000077500000000000000000000000001312614575600222275ustar00rootroot00000000000000rspec-puppet-2.6.1/spec/fixtures/modules/orch_app/manifests/000077500000000000000000000000001312614575600242205ustar00rootroot00000000000000rspec-puppet-2.6.1/spec/fixtures/modules/orch_app/manifests/db.pp000066400000000000000000000000331312614575600251420ustar00rootroot00000000000000define orch_app::db( ) { } rspec-puppet-2.6.1/spec/fixtures/modules/orch_app/manifests/init.pp000066400000000000000000000001151312614575600255210ustar00rootroot00000000000000application orch_app ( String $mystring, ) { orch_app::db { $name: } } rspec-puppet-2.6.1/spec/fixtures/modules/relationships/000077500000000000000000000000001312614575600233205ustar00rootroot00000000000000rspec-puppet-2.6.1/spec/fixtures/modules/relationships/manifests/000077500000000000000000000000001312614575600253115ustar00rootroot00000000000000rspec-puppet-2.6.1/spec/fixtures/modules/relationships/manifests/before.pp000066400000000000000000000013131312614575600271120ustar00rootroot00000000000000class relationships::before { notify { 'foo': before => [Notify['bar']], } notify { 'bar': } notify { 'baz': } file { '/tmp/foo': ensure => directory } file { '/tmp/foo/bar': ensure => file, group => 'foo' } notify { 'bazz': before => File['/tmp/foo'] } notify { 'qux': require => File['/tmp/foo/bar'] } Notify['foo'] -> Notify['baz'] Notify['baz'] <- Notify['bar'] class { '::relationship::before::pre': } -> class { '::relationship::before::middle': } -> class { '::relationship::before::post': } } class relationship::before::pre { notify { 'pre': } } class relationship::before::middle { notify { 'middle': } } class relationship::before::post { notify { 'post': } } rspec-puppet-2.6.1/spec/fixtures/modules/relationships/manifests/complex.pp000066400000000000000000000003011312614575600273130ustar00rootroot00000000000000class relationships::complex { notify { 'foo': before => Notify['bar'], } notify { 'bar': before => Notify['baz'], } notify { 'baz': } Notify['baz'] <- Notify['foo'] } rspec-puppet-2.6.1/spec/fixtures/modules/relationships/manifests/notify.pp000066400000000000000000000010271312614575600271620ustar00rootroot00000000000000class relationships::notify { notify { 'foo': notify => Notify['bar'] } notify { 'bar': subscribe => Notify['baz'], } notify { 'baz': } notify { 'gronk': } Notify['gronk'] <~ Notify['baz'] class { '::relationship::notify::pre': } ~> class { '::relationship::notify::middle': } ~> class { '::relationship::notify::post': } } class relationship::notify::pre { notify { 'pre': } } class relationship::notify::middle { notify { 'middle': } } class relationship::notify::post { notify { 'post': } } rspec-puppet-2.6.1/spec/fixtures/modules/relationships/manifests/titles.pp000066400000000000000000000003021312614575600271510ustar00rootroot00000000000000class relationships::titles { file { "/etc/svc": ensure => present, notify => Service["svc-name"], } service { "svc-title": ensure => running, name => "svc-name", } } rspec-puppet-2.6.1/spec/fixtures/modules/structured_data/000077500000000000000000000000001312614575600236315ustar00rootroot00000000000000rspec-puppet-2.6.1/spec/fixtures/modules/structured_data/manifests/000077500000000000000000000000001312614575600256225ustar00rootroot00000000000000rspec-puppet-2.6.1/spec/fixtures/modules/structured_data/manifests/def.pp000066400000000000000000000001751312614575600267240ustar00rootroot00000000000000define structured_data::def($data = {}) { $template = inline_template('<%= @data.inspect %>') notify { "$template": } } rspec-puppet-2.6.1/spec/fixtures/modules/structured_data/manifests/init.pp000066400000000000000000000001321312614575600271220ustar00rootroot00000000000000class structured_data($data) { structured_data::def { 'thing': data => $data, } } rspec-puppet-2.6.1/spec/fixtures/modules/structured_facts/000077500000000000000000000000001312614575600240205ustar00rootroot00000000000000rspec-puppet-2.6.1/spec/fixtures/modules/structured_facts/functions/000077500000000000000000000000001312614575600260305ustar00rootroot00000000000000rspec-puppet-2.6.1/spec/fixtures/modules/structured_facts/functions/lookup.pp000066400000000000000000000001011312614575600276720ustar00rootroot00000000000000function structured_facts::lookup() { $facts['os']['family'] } rspec-puppet-2.6.1/spec/fixtures/modules/structured_facts/manifests/000077500000000000000000000000001312614575600260115ustar00rootroot00000000000000rspec-puppet-2.6.1/spec/fixtures/modules/structured_facts/manifests/case_check.pp000066400000000000000000000001561312614575600304240ustar00rootroot00000000000000class structured_facts::case_check { $_value = $facts['custom_fact']['MixedCase'] notify { "$_value": } } rspec-puppet-2.6.1/spec/fixtures/modules/structured_facts/manifests/hash.pp000066400000000000000000000001451312614575600272750ustar00rootroot00000000000000class structured_facts::hash { $_os_family = $facts['os']['family'] notify { "$_os_family": } } rspec-puppet-2.6.1/spec/fixtures/modules/structured_facts/manifests/top_scope.pp000066400000000000000000000001421312614575600303420ustar00rootroot00000000000000class structured_facts::top_scope { $_os_family = $::os['family'] notify { "$_os_family": } } rspec-puppet-2.6.1/spec/fixtures/modules/sysctl/000077500000000000000000000000001312614575600217555ustar00rootroot00000000000000rspec-puppet-2.6.1/spec/fixtures/modules/sysctl/manifests/000077500000000000000000000000001312614575600237465ustar00rootroot00000000000000rspec-puppet-2.6.1/spec/fixtures/modules/sysctl/manifests/init.pp000066400000000000000000000015131312614575600252520ustar00rootroot00000000000000class sysctl::common ($test_param = 'yes') { exec { 'sysctl/reload': command => '/sbin/sysctl -p /etc/sysctl.conf', refreshonly => true, returns => [0, 2], } } define sysctl($value) { include sysctl::common augeas { "sysctl/${name}": context => '/files/etc/sysctl.conf', changes => "set ${name} '${value}'", onlyif => "match ${name}[.='${value}'] size == 0", notify => Exec['sysctl/reload'], } } class boolean_test($bool) { $real_bool = $bool ? { true => false, false => true, } if ($real_bool) { notify {"bool testing": message => "This will print when \$bool is false." } } } define sysctl::before($value) { Class['sysctl::common'] -> Sysctl::Before[$name] notify {"message-${name}": message => "This should print if the class is here first." } } rspec-puppet-2.6.1/spec/fixtures/modules/test/000077500000000000000000000000001312614575600214135ustar00rootroot00000000000000rspec-puppet-2.6.1/spec/fixtures/modules/test/functions/000077500000000000000000000000001312614575600234235ustar00rootroot00000000000000rspec-puppet-2.6.1/spec/fixtures/modules/test/functions/hiera_function.pp000066400000000000000000000001011312614575600267510ustar00rootroot00000000000000function test::hiera_function() { hiera('data', 'not found') } rspec-puppet-2.6.1/spec/fixtures/modules/test/lib/000077500000000000000000000000001312614575600221615ustar00rootroot00000000000000rspec-puppet-2.6.1/spec/fixtures/modules/test/lib/puppet/000077500000000000000000000000001312614575600234765ustar00rootroot00000000000000rspec-puppet-2.6.1/spec/fixtures/modules/test/lib/puppet/functions/000077500000000000000000000000001312614575600255065ustar00rootroot00000000000000rspec-puppet-2.6.1/spec/fixtures/modules/test/lib/puppet/functions/frozen_array_function.rb000066400000000000000000000002251312614575600324400ustar00rootroot00000000000000Puppet::Functions.create_function(:frozen_array_function) do def frozen_array_function(value) value.frozen? && value.all?(&:frozen?) end end rspec-puppet-2.6.1/spec/fixtures/modules/test/lib/puppet/functions/frozen_function.rb000066400000000000000000000001601312614575600312400ustar00rootroot00000000000000Puppet::Functions.create_function(:frozen_function) do def frozen_function(value) value.frozen? end end rspec-puppet-2.6.1/spec/fixtures/modules/test/lib/puppet/functions/frozen_hash_function.rb000066400000000000000000000002511312614575600322440ustar00rootroot00000000000000Puppet::Functions.create_function(:frozen_hash_function) do def frozen_hash_function(value) value.frozen? && value.all? { |k,v| k.frozen? && v.frozen? } end end rspec-puppet-2.6.1/spec/fixtures/modules/test/lib/puppet/functions/nil_function.rb000066400000000000000000000002721312614575600305230ustar00rootroot00000000000000Puppet::Functions.create_function(:nil_function) do def nil_function(should_raise) if should_raise raise Puppet::ParseError, 'Forced Failure - new version' end end end rspec-puppet-2.6.1/spec/fixtures/modules/test/lib/puppet/functions/test_function.rb000066400000000000000000000001621312614575600307160ustar00rootroot00000000000000Puppet::Functions.create_function(:test_function) do def test_function(value) "value is #{value}" end end rspec-puppet-2.6.1/spec/fixtures/modules/test/lib/puppet/parser/000077500000000000000000000000001312614575600247725ustar00rootroot00000000000000rspec-puppet-2.6.1/spec/fixtures/modules/test/lib/puppet/parser/functions/000077500000000000000000000000001312614575600270025ustar00rootroot00000000000000rspec-puppet-2.6.1/spec/fixtures/modules/test/lib/puppet/parser/functions/camelCaseFunction.rb000066400000000000000000000004411312614575600327110ustar00rootroot00000000000000module Puppet::Parser::Functions newfunction(:camelCaseFunction, :type => :rvalue) do |args| raise Puppet::ParseError, "Requires 1 argument" unless args.length == 1 raise Puppet::ParseError, "Argument must be a string" unless args.first.is_a?(String) return "test" end end rspec-puppet-2.6.1/spec/fixtures/modules/test/lib/puppet/parser/functions/ensure_packages.rb000066400000000000000000000003471312614575600324720ustar00rootroot00000000000000Puppet::Parser::Functions.newfunction(:ensure_packages, :type => :statement) do |args| Puppet::Parser::Functions.function(:create_resources) function_create_resources(['Package', { args.first => {'ensure' => 'present'} }]) end rspec-puppet-2.6.1/spec/fixtures/modules/test/lib/puppet/parser/functions/nasty.rb000066400000000000000000000001451312614575600304650ustar00rootroot00000000000000Puppet::Parser::Functions.newfunction(:nasty, :type => :rvalue) do |arguments| arguments.shift end rspec-puppet-2.6.1/spec/fixtures/modules/test/lib/puppet/parser/functions/nil_function.rb000066400000000000000000000002351312614575600320160ustar00rootroot00000000000000Puppet::Parser::Functions.newfunction(:nil_function) do |arguments| if arguments[0] raise Puppet::ParseError, 'Forced Failure - old version' end end rspec-puppet-2.6.1/spec/fixtures/modules/test/manifests/000077500000000000000000000000001312614575600234045ustar00rootroot00000000000000rspec-puppet-2.6.1/spec/fixtures/modules/test/manifests/addition.pp000066400000000000000000000001641312614575600255410ustar00rootroot00000000000000define test::addition($value) { $result = $value + 1 # force conversion to string notify { "${result}": } } rspec-puppet-2.6.1/spec/fixtures/modules/test/manifests/bare_class.pp000066400000000000000000000001231312614575600260370ustar00rootroot00000000000000class test::bare_class { notify { 'foo': } include dynamic::create_resources } rspec-puppet-2.6.1/spec/fixtures/modules/test/manifests/basic.pp000066400000000000000000000001151312614575600250230ustar00rootroot00000000000000class test::basic() { fake { 'foo': three => [{'foo' => 'bar'}], } } rspec-puppet-2.6.1/spec/fixtures/modules/test/manifests/classes_used.pp000066400000000000000000000001671312614575600264260ustar00rootroot00000000000000class test::classes_used { include test::bare_class class { 'test::parameterised_class': text => 'bar', } } rspec-puppet-2.6.1/spec/fixtures/modules/test/manifests/compile_error.pp000066400000000000000000000002131312614575600266020ustar00rootroot00000000000000class test::compile_error { user { 'foo': ensure => present, managehome => true, provider => 'directoryservice', } } rspec-puppet-2.6.1/spec/fixtures/modules/test/manifests/duplicate_alias.pp000066400000000000000000000002351312614575600270700ustar00rootroot00000000000000class test::duplicate_alias { exec { 'foo_bar_1': command => '/bin/echo foo bar', } exec { 'foo_bar_2': command => '/bin/echo foo bar', } } rspec-puppet-2.6.1/spec/fixtures/modules/test/manifests/fail.pp000066400000000000000000000000441312614575600246560ustar00rootroot00000000000000class test::fail { fail("test") } rspec-puppet-2.6.1/spec/fixtures/modules/test/manifests/hiera.pp000066400000000000000000000001251312614575600250330ustar00rootroot00000000000000class test::hiera { $message = hiera('data', 'not found') notify { $message: } } rspec-puppet-2.6.1/spec/fixtures/modules/test/manifests/loop_define.pp000066400000000000000000000000641312614575600262300ustar00rootroot00000000000000define test::loop_define() { package { $name: } } rspec-puppet-2.6.1/spec/fixtures/modules/test/manifests/parameterised_class.pp000066400000000000000000000001231312614575600277530ustar00rootroot00000000000000class test::parameterised_class($text, $something = undef) { notify { $text: } } rspec-puppet-2.6.1/spec/fixtures/modules/test/manifests/provider_suitability.pp000066400000000000000000000004031312614575600302160ustar00rootroot00000000000000class test::provider_suitability { $my_managehome = $::osfamily ? { 'Darwin' => 'false', default => true, } file { '/home': ensure => directory } user { 'testuser': managehome => $my_managehome, home => '/home/testuser', } } rspec-puppet-2.6.1/spec/fixtures/modules/test/manifests/user.pp000066400000000000000000000001261312614575600247220ustar00rootroot00000000000000class test::user { user { 'luke': ensure => present, uid => '501', } } rspec-puppet-2.6.1/spec/fixtures/modules/test/manifests/windows.pp000066400000000000000000000002011312614575600254300ustar00rootroot00000000000000class test::windows { file { 'C:\\test.txt': content => 'something', ensure => file, provider => windows, } } rspec-puppet-2.6.1/spec/fixtures/modules/trusted_facts/000077500000000000000000000000001312614575600233065ustar00rootroot00000000000000rspec-puppet-2.6.1/spec/fixtures/modules/trusted_facts/functions/000077500000000000000000000000001312614575600253165ustar00rootroot00000000000000rspec-puppet-2.6.1/spec/fixtures/modules/trusted_facts/functions/lookup.pp000066400000000000000000000001051312614575600271640ustar00rootroot00000000000000function trusted_facts::lookup( String $key ) { $trusted[$key] } rspec-puppet-2.6.1/spec/fixtures/modules/trusted_facts/manifests/000077500000000000000000000000001312614575600252775ustar00rootroot00000000000000rspec-puppet-2.6.1/spec/fixtures/modules/trusted_facts/manifests/init.pp000066400000000000000000000006131312614575600266030ustar00rootroot00000000000000class trusted_facts { notify { "certname-${trusted['certname']}": } notify { "authenticated-${trusted['authenticated']}": } notify { "domain-${trusted['domain']}": } notify { "hostname-${trusted['hostname']}": } if $trusted['extensions'] == {} { notify { "no-extensions": } } else { $trusted['extensions'].each |$k, $v| { notify { "extension-${k}-${v}": } } } } rspec-puppet-2.6.1/spec/fixtures/modules/undef_test/000077500000000000000000000000001312614575600225745ustar00rootroot00000000000000rspec-puppet-2.6.1/spec/fixtures/modules/undef_test/manifests/000077500000000000000000000000001312614575600245655ustar00rootroot00000000000000rspec-puppet-2.6.1/spec/fixtures/modules/undef_test/manifests/def.pp000066400000000000000000000001231312614575600256600ustar00rootroot00000000000000define undef_test::def( $required_attribute, $defaults_to_undef = undef, ) { } rspec-puppet-2.6.1/spec/fixtures/modules/undef_test/manifests/init.pp000066400000000000000000000001151312614575600260660ustar00rootroot00000000000000class undef_test( $required_attribute, $defaults_to_undef = undef, ) { } rspec-puppet-2.6.1/spec/functions/000077500000000000000000000000001312614575600171235ustar00rootroot00000000000000rspec-puppet-2.6.1/spec/functions/camelCaseFunction_spec.rb000066400000000000000000000005221312614575600240440ustar00rootroot00000000000000require 'spec_helper' describe 'camelCaseFunction' do it { should_not be_nil } it { should run.with_params().and_raise_error(Puppet::ParseError, /Requires 1 argument/) } it { should run.with_params(1).and_raise_error(Puppet::ParseError, /Argument must be a string/) } it { should run.with_params('test').and_return('test') } end rspec-puppet-2.6.1/spec/functions/catalogue_spec.rb000066400000000000000000000007621312614575600224330ustar00rootroot00000000000000require 'spec_helper' describe 'split' do describe 'rspec group' do it 'should have a catalogue method' do expect(catalogue).to be_a(Puppet::Resource::Catalog) end it 'catalogue should not change after subject is called' do expect(catalogue).to be_a(Puppet::Resource::Catalog) pre_id = catalogue.object_id should run.with_params('aoeu', 'o').and_return(['a', 'eu']) post_id = catalogue.object_id expect(pre_id).to eq post_id end end end rspec-puppet-2.6.1/spec/functions/cleanup_spec.rb000066400000000000000000000005541312614575600221150ustar00rootroot00000000000000require 'spec_helper' describe '#rspec_puppet_cleanup' do it { expect(respond_to?(:rspec_puppet_cleanup)).to be true } it 'should wipe @catalogue' do @catalogue = Object.new @compiler = Object.new @scope = Object.new rspec_puppet_cleanup expect(@catalogue).to be_nil expect(@compiler).to be_nil expect(@scope).to be_nil end end rspec-puppet-2.6.1/spec/functions/ensure_packages_spec.rb000066400000000000000000000004731312614575600236250ustar00rootroot00000000000000require 'spec_helper' describe 'ensure_packages' do before { subject.call(['facter']) } it 'should create the resource in the catalogue' do expect(catalogue).to contain_package('facter').with_ensure('present') expect(lambda { catalogue }).to contain_package('facter').with_ensure('present') end end rspec-puppet-2.6.1/spec/functions/facts_lookup_spec.rb000066400000000000000000000006711312614575600231570ustar00rootroot00000000000000require 'rspec-puppet' describe 'structured_facts::lookup', :if => Puppet::Util::Package.versioncmp(Puppet.version, '4.3.0') >= 0 do context 'with one set of values' do let(:facts) {{ 'os' => {'family' => 'RedHat'} }} it { is_expected.to run.and_return('RedHat') } end context 'with a different set of values' do let(:facts) {{ 'os' => {'family' => 'Suse'} }} it { is_expected.to run.and_return('Suse') } end end rspec-puppet-2.6.1/spec/functions/lambda_function_spec.rb000066400000000000000000000002671312614575600236140ustar00rootroot00000000000000require 'spec_helper' describe 'map', :if => Puppet.version.to_i >= 4 do it { should run.with_params([1, 2]).with_lambda { |x| "test-#{x}" }.and_return(['test-1', 'test-2']) } end rspec-puppet-2.6.1/spec/functions/nasty_spec.rb000066400000000000000000000007431312614575600216240ustar00rootroot00000000000000require 'spec_helper' describe 'nasty' do it { expect(subject).not_to eq(nil) } it { expect(subject).to run.with_params('foo', 'bar').and_return('foo') } describe 'the underlying Run matcher' do it 'should not have its description manipulated by running the function' do run_matcher = run.with_params('foo', 'bar').and_return('foo') should run_matcher expect(run_matcher.description).to eq('run nasty("foo", "bar") and return "foo"') end end end rspec-puppet-2.6.1/spec/functions/nil_function_spec.rb000066400000000000000000000007041312614575600231520ustar00rootroot00000000000000require 'spec_helper' describe 'nil_function' do it { should run.with_params(false).and_return(nil) } it { should run.with_params(true).and_raise_error(Puppet::ParseError, /Forced Failure/) } let(:version) do if Puppet[:parser] == 'future' or Puppet.version.to_f >= 4 'new version' else 'old version' end end it { should run.with_params(true).and_raise_error(Puppet::ParseError, /Forced Failure - #{version}/) } end rspec-puppet-2.6.1/spec/functions/regsubst_spec.rb000066400000000000000000000007021312614575600223170ustar00rootroot00000000000000require 'spec_helper' describe 'regsubst' do # used to test the fact that expected result can be a regexp it { should run.with_params('thisisatest', '^192', '254').and_return(/sat/) } it { should run.with_params('thisisatest', 'sat', 'xyz').and_return(/ixyze/) } it { should run.with_params('thisisatest', 'sat', 'xyz').and_return('thisixyzest') } it { should run.with_params('thisisatest', 'sat', 'xyz').and_return(/^thisixyzest$/) } end rspec-puppet-2.6.1/spec/functions/split_spec.rb000066400000000000000000000023151312614575600216160ustar00rootroot00000000000000require 'spec_helper' describe 'split' do it { should run.with_params('aoeu', 'o').and_return(['a', 'eu']) } it { should_not run.with_params('foo').and_raise_error(Puppet::DevError) } if Puppet::Util::Package.versioncmp(Puppet.version, '3.1.0') >= 0 expected_error = ArgumentError else expected_error = Puppet::ParseError end if Puppet::Util::Package.versioncmp(Puppet.version, '4.3.0') >= 0 expected_error_message = /expects \d+ arguments/ elsif Puppet::Util::Package.versioncmp(Puppet.version, '4.0.0') >= 0 expected_error_message = /mis-matched arguments/ else expected_error_message = /number of arguments/ end it { should run.with_params('foo').and_raise_error(expected_error) } it { should run.with_params('foo').and_raise_error(expected_error, expected_error_message) } it { should run.with_params('foo').and_raise_error(expected_error_message) } it { expect { should run.with_params('foo').and_raise_error(/definitely no match/) }.to raise_error RSpec::Expectations::ExpectationNotMetError } context 'after including a class' do let(:pre_condition) { 'include ::sysctl::common' } it { should run.with_params('aoeu', 'o').and_return(['a', 'eu']) } end end rspec-puppet-2.6.1/spec/functions/test_function_spec.rb000066400000000000000000000011511312614575600233440ustar00rootroot00000000000000require 'spec_helper' describe 'test_function', :if => Puppet.version.to_f >= 4.0 do # Verify that we can load functions from modules it { is_expected.to run.with_params('foo').and_return(/value is foo/) } end describe 'frozen_function', :if => Puppet.version.to_f >= 4.0 do it { is_expected.to run.with_params('foo').and_return(true) } it { is_expected.to run.with_params(String).and_return(false) } it { is_expected.to run.with_params(true).and_return(true) } it { is_expected.to run.with_params(['foo']).and_return(true) } it { is_expected.to run.with_params('foo' => 'bar').and_return(true) } end rspec-puppet-2.6.1/spec/functions/test_hiera_function_spec.rb000066400000000000000000000005561312614575600245240ustar00rootroot00000000000000require 'spec_helper' describe 'test::hiera_function', :if => Puppet::Util::Package.versioncmp(Puppet.version, '4.3.0') >= 0 do context 'with :hiera_config set' do let(:hiera_config) { 'spec/fixtures/hiera.yaml' } it { should run.and_return('foo') } end context 'without :hiera_config set' do it { should run.and_return('not found') } end end rspec-puppet-2.6.1/spec/functions/test_type_override_spec.rb000066400000000000000000000003551312614575600244040ustar00rootroot00000000000000require 'spec_helper' # :type should override the type inferred from the file's location in spec/functions/ describe 'test::bare_class', :type => :class, :if => RSpec::Version::STRING >= '3' do it { should compile.with_all_deps } end rspec-puppet-2.6.1/spec/functions/trusted_facts_lookup_spec.rb000066400000000000000000000014601312614575600247260ustar00rootroot00000000000000require 'spec_helper' describe 'trusted_facts::lookup', :if => Puppet::Util::Package.versioncmp(Puppet.version, '4.3.0') >= 0 do let(:node) { 'trusted.example.com' } context 'without trusted fact extensions' do it { is_expected.to run.with_params('certname').and_return(node) } it { is_expected.to run.with_params('hostname').and_return('trusted') } it { is_expected.to run.with_params('domain').and_return('example.com') } it { is_expected.to run.with_params('authenticated').and_return('remote') } it { is_expected.to run.with_params('extensions').and_return({}) } end context 'with trusted fact extensions' do let(:trusted_facts) {{ 'extra1' => '1', 'extra2' => '2' }} it { is_expected.to run.with_params('extensions').and_return(trusted_facts) } end end rspec-puppet-2.6.1/spec/hosts/000077500000000000000000000000001312614575600162535ustar00rootroot00000000000000rspec-puppet-2.6.1/spec/hosts/array_spec.rb000066400000000000000000000003511312614575600207270ustar00rootroot00000000000000require 'spec_helper' describe 'someotherhost' do let(:pre_condition) { <<-EOF define foo($param) { } foo { 'bar': param => ['baz'], } EOF } it { should contain_foo('bar').with_param(['baz']) } end rspec-puppet-2.6.1/spec/hosts/cleanup_spec.rb000066400000000000000000000003741312614575600212450ustar00rootroot00000000000000require 'spec_helper' describe '#rspec_puppet_cleanup' do it { expect(respond_to?(:rspec_puppet_cleanup)).to be true } it 'should wipe @catalogue' do @catalogue = Object.new rspec_puppet_cleanup expect(@catalogue).to be_nil end end rspec-puppet-2.6.1/spec/hosts/environment_spec.rb000066400000000000000000000007711312614575600221630ustar00rootroot00000000000000require 'spec_helper' describe 'facts.acme.com' do context 'without an explicit environment setting' do it { should contain_file('environment').with_path('rp_env') } end # Broken on ~> 3.8.5 since PUP-5522 context 'when specifying an explicit environment', :unless => (Puppet.version >= '3.8.5' && Puppet.version.to_i < 4) do let(:environment) { 'test_env' } it { should contain_file('environment').with_path('test_env') } it { should contain_file('conditional_file') } end end rspec-puppet-2.6.1/spec/hosts/facts_spec.rb000066400000000000000000000007151312614575600207150ustar00rootroot00000000000000require 'spec_helper' describe 'facts.acme.com' do it { should contain_file('environment').with_path('rp_env') } it { should contain_file('clientversion').with_path(Puppet::PUPPETVERSION) } it { should contain_file('fqdn').with_path('facts.acme.com') } it { should contain_file('hostname').with_path('facts') } it { should contain_file('domain').with_path('acme.com') } it { should contain_file('clientcert').with_path('cert facts.acme.com') } end rspec-puppet-2.6.1/spec/hosts/foo_spec.rb000066400000000000000000000002241312614575600203730ustar00rootroot00000000000000require 'spec_helper' describe 'foo.example.com' do it { should_not contain_class('sysctl::common') } it { should contain_notify('test') } end rspec-puppet-2.6.1/spec/hosts/good_dep_host_spec.rb000066400000000000000000000001351312614575600224260ustar00rootroot00000000000000require 'spec_helper' describe 'good_dep_host' do it { should compile.with_all_deps } end rspec-puppet-2.6.1/spec/hosts/test_api_spec.rb000066400000000000000000000010471312614575600214240ustar00rootroot00000000000000require 'spec_helper' describe 'foo.example.com' do describe 'rspec group' do it 'should have a catalogue method' do expect(catalogue).to be_a(Puppet::Resource::Catalog) end it 'subject should return a catalogue' do expect(subject.call).to be_a(Puppet::Resource::Catalog) end it 'should have resources in its coverage report' do expect(RSpec::Puppet::Coverage.instance.results[:total]).to be > 0 expect(RSpec::Puppet::Coverage.instance.results[:resources]).to include('Notify[test]') end end end rspec-puppet-2.6.1/spec/hosts/testhost_spec.rb000066400000000000000000000004031312614575600214640ustar00rootroot00000000000000require 'spec_helper' describe 'testhost' do it { should contain_class('sysctl::common') } describe 'testhost_a' do let(:node) { 'testhost_a' } it { should_not contain_class('sysctl::common') } it { should contain_file('/tmp/a') } end end rspec-puppet-2.6.1/spec/raw_string_spec.rb000066400000000000000000000004071312614575600206320ustar00rootroot00000000000000require 'rspec-puppet/raw_string' describe RSpec::Puppet::RawString do describe '#inspect' do it 'returns the raw string when doing an inspect' do expect(RSpec::Puppet::RawString.new('my_raw_string').inspect).to eq('my_raw_string') end end end rspec-puppet-2.6.1/spec/spec_helper.rb000066400000000000000000000010421312614575600177260ustar00rootroot00000000000000if ENV['COVERAGE'] == 'yes' require 'coveralls' Coveralls.wear! end require 'rspec-puppet' RSpec.configure do |c| c.module_path = File.join(File.dirname(File.expand_path(__FILE__)), 'fixtures', 'modules') c.manifest_dir = File.join(File.dirname(File.expand_path(__FILE__)), 'fixtures', 'manifests') c.manifest = File.join(File.dirname(File.expand_path(__FILE__)), 'fixtures', 'manifests', 'site.pp') c.environmentpath = File.join(Dir.pwd, 'spec') c.after(:suite) do RSpec::Puppet::Coverage.report!(0) end end rspec-puppet-2.6.1/spec/support_spec.rb000066400000000000000000000060141312614575600201670ustar00rootroot00000000000000require 'spec_helper' require 'rspec-puppet/adapters' describe RSpec::Puppet::Support do subject do Object.new.extend(RSpec::Puppet::Support) end describe '#setup_puppet' do before do adapter = RSpec::Puppet::Adapters.get adapter.setup_puppet(subject) subject.adapter = adapter end it 'updates the ruby $LOAD_PATH based on the current modulepath' do basedir = RSpec.configuration.module_path dira = File.join(basedir, 'a', 'lib') dirb = File.join(basedir, 'b', 'lib') allow(Dir).to receive(:[]).with("#{basedir}/*/lib").and_return([dira, dirb]) subject.setup_puppet expect($LOAD_PATH).to include(dira) expect($LOAD_PATH).to include(dirb) end end describe "#ref" do it 'should return a new RawString with the type/title format' do expect(subject.ref('Package','tomcat').inspect).to eq("Package['tomcat']") end end describe '#str_from_value' do it "should quote strings" do expect(subject.str_from_value('a string')).to eq('"a string"') end it "should not quote numbers" do expect(subject.str_from_value(100)).to eq('100') expect(subject.str_from_value(-42)).to eq('-42') expect(subject.str_from_value(3.14)).to eq('3.14') end it "should use literal 'default' when receiving :default" do expect(subject.str_from_value(:default)).to eq('default') end it "should use literal 'undef' when receiving :undef" do expect(subject.str_from_value(:undef)).to eq('undef') end it "should convert Symbols to Strings" do expect(subject.str_from_value(:a_symbol)).to eq('"a_symbol"') end it "should handle Arrays recursively" do expect(subject.str_from_value([1,2,3])).to eq('[ 1, 2, 3 ]') end it "should handle Hashes recursively" do expect(subject.str_from_value({:k1=>'v1'})).to eq('{ "k1" => "v1" }') expect(subject.str_from_value({'k2'=>'v2'})).to eq('{ "k2" => "v2" }') end end describe '#build_code' do before do class << subject def class_name "class_name" end def site_pp_str "" end def import_str "" end end end context "without any properties" do it "builds a test manifest" do expect(subject.build_code(:class, {})).to eq "\ninclude class_name" end end context "with a pre_condition available" do before do class << subject def pre_condition "pre_condition" end end end it "builds a test manifest" do expect(subject.build_code(:class, {})).to eq "\npre_condition\ninclude class_name" end end context "with a post_condition available" do before do class << subject def post_condition "post_condition" end end end it "builds a test manifest" do expect(subject.build_code(:class, {})).to eq "\ninclude class_name\npost_condition" end end end end rspec-puppet-2.6.1/spec/type_aliases/000077500000000000000000000000001312614575600175755ustar00rootroot00000000000000rspec-puppet-2.6.1/spec/type_aliases/onlyarray_spec.rb000066400000000000000000000003521312614575600231540ustar00rootroot00000000000000require 'spec_helper' describe 'Aliases::OnlyArray', :if => Puppet::Util::Package.versioncmp(Puppet.version, '4.4.0') >= 0 do it { is_expected.not_to allow_value(nil, 'string') } it { is_expected.to allow_value(['a', 'b']) } end rspec-puppet-2.6.1/spec/type_aliases/onlyhash_spec.rb000066400000000000000000000004461312614575600227650ustar00rootroot00000000000000require 'spec_helper' describe 'Aliases::OnlyHash', :if => Puppet::Util::Package.versioncmp(Puppet.version, '4.4.0') >= 0 do it { is_expected.not_to allow_value(nil, 'string') } it { is_expected.to allow_value({'a' => 'b'}) } it { is_expected.to allow_value({'a' => {'b' => 'c'}}) } end rspec-puppet-2.6.1/spec/type_aliases/shape_spec.rb000066400000000000000000000006601312614575600222360ustar00rootroot00000000000000require 'spec_helper' describe 'Aliases::Shape', :if => Puppet::Util::Package.versioncmp(Puppet.version, '4.4.0') >= 0 do it { is_expected.to allow_value('square') } it { is_expected.to allow_value('circle') } it { is_expected.not_to allow_value('triangle') } it { is_expected.not_to allow_value(nil) } it { is_expected.to allow_values('square', 'circle') } it { is_expected.not_to allow_values('triangle', nil) } end rspec-puppet-2.6.1/spec/types/000077500000000000000000000000001312614575600162575ustar00rootroot00000000000000rspec-puppet-2.6.1/spec/types/cleanup_spec.rb000066400000000000000000000004141312614575600212440ustar00rootroot00000000000000require 'spec_helper' describe '#rspec_puppet_cleanup' do it { expect(respond_to?(:rspec_puppet_cleanup)).to be true } it 'should wipe @catalogue' do @type_and_resource = Object.new rspec_puppet_cleanup expect(@type_and_resource).to be_nil end end rspec-puppet-2.6.1/spec/types/valid_provider_spec.rb000066400000000000000000000041321312614575600226270ustar00rootroot00000000000000require 'spec_helper' describe 'fake' do let :title do 'foo' end it { should be_valid_type } describe 'tests of the types' do { :parameters => {:baddies => ['one', 'two'], :goodies => ['three', 'four']}, :properties => {:baddies => ['five', 'fix'], :goodies => ['seven', 'eight']}, :features => {:baddies => ['nine', 'ten'], :goodies => ['eleven', 'twelve']} }.each do |k, v| describe "#{k} checks" do [v[:baddies], v[:baddies].first].each do |baddies| it "should fail for #{baddies.size} baddies" do expect do should be_valid_type.send("with_#{k}".to_sym, baddies) end.to raise_error( RSpec::Expectations::ExpectationNotMetError, /Invalid #{k}: #{Array(baddies).join(',')}/ ) end end [v[:goodies], v[:goodies].first].each do |goodies| it "should pass with #{goodies.size} goodies" do should be_valid_type.send("with_#{k}".to_sym, goodies) end end end end end describe 'tests that create a resource instance' do let :params do { :three => 'value' } end it 'should pass when providers match' do should be_valid_type.with_provider(:default) end it 'should fail when provider does not match' do expect do should be_valid_type.with_provider(:non_matching) end.to raise_error( RSpec::Expectations::ExpectationNotMetError, /Expected provider: non_matching does not match: default/ ) end it 'should pass when providers match' do should be_valid_type.with_provider(:default) end it 'should fail with invalid parameters' do expect do should be_valid_type.with_set_attributes( :four => 'three' ) end.to raise_error( Puppet::Error, /Valid values match \/\(one\|two\)\// ) end it 'should not fail with valid parameters' do should be_valid_type.with_set_attributes( :four => 'one' ) end end end rspec-puppet-2.6.1/spec/unit/000077500000000000000000000000001312614575600160725ustar00rootroot00000000000000rspec-puppet-2.6.1/spec/unit/adapters_spec.rb000066400000000000000000000135071312614575600212420ustar00rootroot00000000000000require 'spec_helper' require 'rspec-puppet/adapters' def context_double(options = {}) double({:environment => 'rp_puppet'}.merge(options)) end describe RSpec::Puppet::Adapters::Base do describe '#setup_puppet' do it "sets up all settings listed in the settings map" do context = context_double expected_settings = Hash[*subject.settings_map.map { |r| [r.first, anything] }.flatten] expect(Puppet.settings).to receive(:initialize_app_defaults).with(hash_including(expected_settings)) subject.setup_puppet(context) end end describe '#set_setting' do describe "with a context specific setting" do it "sets the Puppet setting based on the example group setting" do context = context_double :confdir => "/etc/fingerpuppet" subject.setup_puppet(context) expect(Puppet[:confdir]).to match(%r{(C:)?/etc/fingerpuppet}) end it "does not persist settings between example groups" do context1 = context_double :confdir => "/etc/fingerpuppet" context2 = context_double subject.setup_puppet(context1) expect(Puppet[:confdir]).to match(%r{(C:)?/etc/fingerpuppet}) subject.setup_puppet(context2) expect(Puppet[:confdir]).to match(%r{(C:)?/etc/puppet}) end end describe "with a global RSpec configuration setting" do before do allow(RSpec.configuration).to receive(:confdir).and_return("/etc/bunraku") end it "sets the Puppet setting based on the global configuration value" do subject.setup_puppet(context_double) expect(Puppet[:confdir]).to match(%r{(C:)?/etc/bunraku}) end end describe "with both a global RSpec configuration setting and a context specific setting" do before do allow(RSpec.configuration).to receive(:confdir).and_return("/etc/bunraku") end it "prefers the context specific setting" do context = context_double :confdir => "/etc/sockpuppet" subject.setup_puppet(context) expect(Puppet[:confdir]).to match(%r{(C:)?/etc/sockpuppet}) end end describe "when the setting is not available on the given version of Puppet" do it "logs a warning about the setting" do end end end end describe RSpec::Puppet::Adapters::Adapter3X, :if => (3.0 ... 4.0).include?(Puppet.version.to_f) do let(:test_context) { double :environment => 'rp_env' } context 'when running on puppet 3.5 or later', :if => (3.5 ... 4.0).include?(Puppet.version.to_f) do it 'sets Puppet[:strict_variables] to false by default' do subject.setup_puppet(test_context) expect(Puppet[:strict_variables]).to eq(false) end it 'reads the :strict_variables setting' do allow(test_context).to receive(:strict_variables).and_return true subject.setup_puppet(test_context) expect(Puppet[:strict_variables]).to eq(true) end end context 'when running on puppet 3.x, with x >= 5', :if => (3.5 ... 4.0).include?(Puppet.version.to_f) do it 'sets Puppet[:trusted_node_data] to false by default' do subject.setup_puppet(test_context) expect(Puppet[:trusted_node_data]).to eq(false) end it 'reads the :trusted_node_data setting' do allow(test_context).to receive(:trusted_node_data).and_return(true) subject.setup_puppet(test_context) expect(Puppet[:trusted_node_data]).to eq(true) end end context 'when running on puppet ~> 3.2', :if => (3.2 ... 4.0).include?(Puppet.version.to_f) do it 'sets Puppet[:parser] to "current" by default' do subject.setup_puppet(test_context) expect(Puppet[:parser]).to eq("current") end it 'reads the :parser setting' do allow(test_context).to receive(:parser).and_return("future") subject.setup_puppet(test_context) expect(Puppet[:parser]).to eq("future") end end context 'when running on puppet ~> 3.3', :if => (3.3 ... 4.0).include?(Puppet.version.to_f) do it 'sets Puppet[:stringify_facts] to true by default' do subject.setup_puppet(test_context) expect(Puppet[:stringify_facts]).to eq(true) end it 'reads the :stringify_facts setting' do allow(test_context).to receive(:stringify_facts).and_return false subject.setup_puppet(test_context) expect(Puppet[:stringify_facts]).to eq(false) end it 'sets Puppet[:ordering] to title-hash by default' do subject.setup_puppet(test_context) expect(Puppet[:ordering]).to eq('title-hash') end it 'reads the :ordering setting' do allow(test_context).to receive(:ordering).and_return("manifest") subject.setup_puppet(test_context) expect(Puppet[:ordering]).to eq('manifest') end end end describe RSpec::Puppet::Adapters::Adapter4X, :if => Puppet.version.to_f >= 4.0 do let(:test_context) { double :environment => 'rp_env' } it 'sets Puppet[:strict_variables] to false by default' do subject.setup_puppet(test_context) expect(Puppet[:strict_variables]).to eq(false) end it 'reads the :strict_variables setting' do allow(test_context).to receive(:strict_variables).and_return(true) subject.setup_puppet(test_context) expect(Puppet[:strict_variables]).to eq(true) end describe '#manifest' do it 'returns the configured environment manifest when set' do allow(RSpec.configuration).to receive(:manifest).and_return("/path/to/manifest") subject.setup_puppet(double(:environment => 'rp_puppet')) expect(subject.manifest).to match(%r{(C:)?/path/to/manifest}) end it 'returns nil when the configured environment manifest is not set' do allow(RSpec.configuration).to receive(:manifest) allow(RSpec.configuration).to receive(:environmentpath).and_return("/some/missing/path:/another/missing/path") subject.setup_puppet(double(:environment => 'rp_puppet')) expect(subject.manifest).to be_nil end end end rspec-puppet-2.6.1/spec/unit/coverage_spec.rb000066400000000000000000000061011312614575600212220ustar00rootroot00000000000000require 'spec_helper' require 'rspec-puppet/coverage' require 'rspec-puppet/support' describe RSpec::Puppet::Coverage do subject { described_class.new } # Save and restore the global coverage object so that these tests don't # affect the actual spec coverage before(:all) do @saved = described_class.instance described_class.instance = described_class.new end after(:all) do described_class.instance = @saved end describe "filtering" do it "filters boilerplate catalog resources by default" do expect(subject.filters).to eq %w[Stage[main] Class[Settings] Class[main] Node[default]] end it "can add additional filters" do subject.add_filter("notify", "ignore me") expect(subject.filters).to include("Notify[ignore me]") subject.add_filter("foo::bar", "ignore me") expect(subject.filters).to include("Foo::Bar[ignore me]") subject.add_filter("class", "foo::bar") expect(subject.filters).to include("Class[Foo::Bar]") end it "filters resources based on the resource title" do # TODO: this is evil and uses duck typing on `#to_s` to work. fake_resource = "Stage[main]" expect(subject.filtered?(fake_resource)).to be end end describe "adding resources that could be covered" do it "adds resources that don't exist and aren't filtered" do expect(subject.add("Notify[Add me]")).to be end it "ignores resources that have been filtered" do subject.add_filter("notify", "ignore me") expect(subject.add("Notify[ignore me]")).to_not be subject.add_filter("foo::bar", "ignore me") expect(subject.add("Foo::Bar[ignore me]")).to_not be subject.add_filter("class", "foo::bar") expect(subject.add("Class[Foo::Bar]")).to_not be end it "ignores resources that have already been added" do subject.add("Notify[Ignore the duplicate]") expect(subject.add("Notify[Ignore the duplicate]")).to_not be end end describe "getting coverage results" do let(:touched) { %w[First Second Third Fourth Fifth] } let(:untouched) { %w[Sixth Seventh Eighth Nineth] } before do touched.each do |title| subject.add("Notify[#{title}]") subject.cover!("Notify[#{title}]") end untouched.each do |title| subject.add("Notify[#{title}]") end end let(:report) { subject.results } it "counts the total number of resources" do expect(report[:total]).to eq 9 end it "counts the number of touched resources" do expect(report[:touched]).to eq 5 end it "counts the number of untouched resources" do expect(report[:untouched]).to eq 4 end it "counts the coverage percentage" do expect(report[:coverage]).to eq "55.56" end it "includes all resources and their status" do resources = report[:resources] touched.each do |name| expect(resources["Notify[#{name}]"]).to eq(:touched => true) end untouched.each do |name| expect(resources["Notify[#{name}]"]).to eq(:touched => false) end end end end rspec-puppet-2.6.1/spec/unit/example/000077500000000000000000000000001312614575600175255ustar00rootroot00000000000000rspec-puppet-2.6.1/spec/unit/example/function_example_group_spec.rb000066400000000000000000000024401312614575600256400ustar00rootroot00000000000000require 'spec_helper' if Puppet.version.to_f >= 4.0 describe RSpec::Puppet::FunctionExampleGroup::V4FunctionWrapper do let(:name) { 'test_function' } let(:func) { double('func') } let(:global_scope) { double('global_scope') } let(:overrides) { { :global_scope => global_scope } } describe 'when calling with params' do subject { described_class.new(name, func, overrides) } it do expect(func).to receive(:call).with(global_scope, 1, 2).once subject.call({}, 1, 2) end end describe 'when executing with params' do subject { described_class.new(name, func, overrides) } it do expect(func).to receive(:call).with(global_scope, 1, 2).once subject.execute(1, 2) end end end end describe RSpec::Puppet::FunctionExampleGroup::V3FunctionWrapper do let(:name) { 'test_function' } let(:func) { double('func') } describe 'when calling with params' do subject { described_class.new(name, func) } it do expect(func).to receive(:call).with([1, 2]).once subject.call([1, 2]) end end describe 'when executing with params' do subject { described_class.new(name, func) } it do expect(func).to receive(:call).with([1, 2]).once subject.execute(1, 2) end end end rspec-puppet-2.6.1/spec/unit/matchers/000077500000000000000000000000001312614575600177005ustar00rootroot00000000000000rspec-puppet-2.6.1/spec/unit/matchers/allow_value_spec.rb000066400000000000000000000062331312614575600235550ustar00rootroot00000000000000require 'spec_helper' require 'rspec-puppet/support' # is_expected.to not available with rspec 2.14, which is only used for puppet < 3 describe RSpec::Puppet::TypeAliasMatchers::AllowValue, :if => Puppet.version.to_f >= 3.0 do subject { RSpec::Puppet::TypeAliasMatchers::AllowValue.new(values) } let(:catalogue) { double('catalogue builder') } describe "one matching value" do let (:values) { ['circle'] } before { allow(catalogue).to receive(:call).with('circle') } describe '#matches?' do it { expect(subject.matches?(catalogue)).to be true } end describe '#description' do it { expect(subject.description).to eq('match value "circle"') } end end describe "one incorrect value" do let (:values) { ['circle'] } before { allow(catalogue).to receive(:call).with('circle').and_raise(Puppet::Error.new('expected a Shape value, got circle')) } describe '#matches?' do it { expect(subject.matches?(catalogue)).to be false } end describe '#description' do it { expect(subject.description).to eq('match value "circle"') } end describe '#failure_message' do before { subject.matches?(catalogue) } it { expect(subject.failure_message).to eq('expected that the type alias would match value "circle" but it raised the error expected a Shape value, got circle') } end describe '#failure_message_when_negated' do it { expect(subject.failure_message_when_negated).to eq('expected that the type alias would not match value "circle" but it does') } end end describe "multiple matching values" do let (:values) { ['circle', 'square'] } before do allow(catalogue).to receive(:call).with('circle') allow(catalogue).to receive(:call).with('square') end describe '#matches?' do it { expect(subject.matches?(catalogue)).to be true } end describe '#description' do it { expect(subject.description).to eq('match values "circle", "square"') } end end describe "mixed matching/incorrect values" do let (:values) { ['circle', 'square', 'triangle'] } before do allow(catalogue).to receive(:call).with('circle').and_raise(Puppet::Error.new('expected a Shape value, got circle')) allow(catalogue).to receive(:call).with('triangle').and_raise(Puppet::Error.new('expected a Shape value, got triangle')) allow(catalogue).to receive(:call).with('square') end describe '#matches?' do it { expect(subject.matches?(catalogue)).to be false } end describe '#description' do it { expect(subject.description).to eq('match values "circle", "square", "triangle"') } end describe '#failure_message' do before { subject.matches?(catalogue) } it { expect(subject.failure_message).to eq('expected that the type alias would match values "circle", "square", "triangle" but it raised the errors expected a Shape value, got circle, expected a Shape value, got triangle') } end describe '#failure_message_when_negated' do it { expect(subject.failure_message_when_negated).to eq('expected that the type alias would not match values "circle", "square", "triangle" but it does') } end end end rspec-puppet-2.6.1/spec/unit/matchers/compile_spec.rb000066400000000000000000000147061312614575600226770ustar00rootroot00000000000000require 'spec_helper' require 'rspec-puppet/support' # is_expected.to and a_string_starting_with not available with rspec 2.14, which is only used for puppet < 3 if Puppet.version.to_f >= 3.0 describe RSpec::Puppet::ManifestMatchers::Compile do include RSpec::Puppet::Support # override RSpec::Puppet::Support's subject with the original default subject { RSpec::Puppet::ManifestMatchers::Compile.new } let(:catalogue) { lambda { load_catalogue(:host) } } describe "a valid manifest" do let (:pre_condition) { 'file { "/tmp/resource": }' } it ("matches") { is_expected.to be_matches catalogue } it { is_expected.to have_attributes( :description => "compile into a catalogue without dependency cycles" )} context "when expecting an \"example\" error" do before(:each) { subject.and_raise_error("example") } it ("doesn't match") { is_expected.to_not be_matches catalogue } it { is_expected.to have_attributes( :description => "fail to compile and raise the error \"example\"" )} context "after matching" do before(:each) { subject.matches? catalogue } it { is_expected.to have_attributes( :failure_message => a_string_starting_with("expected that the catalogue would fail to compile and raise the error \"example\"") )} end end context "when matching an \"example\" error" do before(:each) { subject.and_raise_error(/example/) } it ("doesn't match") { is_expected.to_not be_matches catalogue } it { is_expected.to have_attributes( :description => "fail to compile and raise an error matching /example/" )} context "after matching" do before(:each) { subject.matches? catalogue } it { is_expected.to have_attributes( :failure_message => a_string_starting_with("expected that the catalogue would fail to compile and raise an error matching /example/") )} end end end describe "a manifest with missing dependencies" do let (:pre_condition) { 'file { "/tmp/resource": require => File["/tmp/missing"] }' } it ("doesn't match") { is_expected.to_not be_matches catalogue } context "after matching" do before(:each) { subject.matches? catalogue } it { is_expected.to have_attributes( :failure_message => a_string_matching(%r{\Aerror during compilation: Could not (retrieve dependency|find resource) 'File\[/tmp/missing\]'}) )} end end describe "a manifest with syntax error" do let (:pre_condition) { 'file { "/tmp/resource": ' } it ("doesn't match") { is_expected.to_not be_matches catalogue } context "after matching" do before(:each) { subject.matches? catalogue } it { is_expected.to have_attributes( :failure_message => a_string_starting_with("error during compilation: ") )} end end describe "a manifest with a dependency cycle" do let (:pre_condition) { <<-EOS file { "/tmp/a": require => File["/tmp/b"] } file { "/tmp/b": require => File["/tmp/a"] } EOS } it ("doesn't match") { is_expected.to_not be_matches catalogue } context "after matching" do before(:each) { subject.matches? catalogue } it { is_expected.to have_attributes( :failure_message => a_string_starting_with("dependency cycles found: ") )} end context "when expecting an \"example\" error" do before(:each) { subject.and_raise_error("example") } it ("doesn't match") { is_expected.to_not be_matches catalogue } context "after matching" do before(:each) { subject.matches? catalogue } it { is_expected.to have_attributes( :description => "fail to compile and raise the error \"example\"", :failure_message => a_string_starting_with("dependency cycles found: ") )} end end context "when matching an \"example\" error" do before(:each) { subject.and_raise_error(/example/) } it ("doesn't match") { is_expected.to_not be_matches catalogue } context "after matching" do before(:each) { subject.matches? catalogue } it { is_expected.to have_attributes( :description => "fail to compile and raise an error matching /example/", :failure_message => a_string_starting_with("dependency cycles found: ") )} end end end describe "a manifest with a real failure" do let (:pre_condition) { 'fail("failure")' } it ("doesn't match") { is_expected.to_not be_matches catalogue } context "after matching" do before(:each) { subject.matches? catalogue } it { is_expected.to have_attributes( :description => "compile into a catalogue without dependency cycles", :failure_message => a_string_starting_with("error during compilation: ") )} end context "when expecting the failure" do before(:each) { subject.and_raise_error("Evaluation Error: Error while evaluating a Function Call, failure at line 52:1 on node rspec::puppet::manifestmatchers::compile") } if Puppet.version.to_f >= 4.0 # the error message above is puppet4 specific it ("matches") { is_expected.to be_matches catalogue } end it { is_expected.to have_attributes( :description => "fail to compile and raise the error \"Evaluation Error: Error while evaluating a Function Call, failure at line 52:1 on node rspec::puppet::manifestmatchers::compile\"" )} context "after matching" do before(:each) { subject.matches? catalogue } it { is_expected.to have_attributes( :failure_message => a_string_starting_with("error during compilation: ") )} end end context "when matching the failure" do before(:each) { subject.and_raise_error(/failure/) } it ("matches") { is_expected.to be_matches catalogue } it { is_expected.to have_attributes( :description => "fail to compile and raise an error matching /failure/" )} context "after matching" do before(:each) { subject.matches? catalogue } it { is_expected.to have_attributes( :failure_message => a_string_starting_with("error during compilation: ") )} end end end end end rspec-puppet-2.6.1/spec/unit/matchers/parameter_matcher_spec.rb000066400000000000000000000055671312614575600247370ustar00rootroot00000000000000require 'spec_helper' describe RSpec::Puppet::ManifestMatchers::ParameterMatcher do describe '#matches?' do context 'with [1] expected' do subject do described_class.new(:foo_parameter, [1], :should) end it 'matches [1]' do expect(subject.matches?(:foo_parameter => [1])).to be(true) end it 'does not match []' do expect(subject.matches?(:foo_parameter => [])).to be(false) end it 'does not match [1,2,3]' do expect(subject.matches?(:foo_parameter => [1,2,3])).to be(false) end it 'does not match nil' do expect(subject.matches?(:foo_parameter => nil)).to be(false) end end context 'with [1,2,3] expected' do subject do described_class.new(:foo_parameter, [1,2,3], :should) end it 'matches [1,2,3]' do expect(subject.matches?(:foo_parameter => [1,2,3])).to be(true) end it 'does not match []' do expect(subject.matches?(:foo_parameter => [])).to be(false) end it 'does not match nil' do expect(subject.matches?(:foo_parameter => nil)).to be(false) end end context 'with {"foo" => "bar"} expected' do subject do described_class.new(:foo_parameter, {"foo" => "bar"}, :should) end it 'matches {"foo" => "bar"}' do expect(subject.matches?(:foo_parameter => {"foo" => "bar"})).to be(true) end it 'does not match nil' do expect(subject.matches?(:foo_parameter => nil)).to be(false) end it 'does not match {}' do expect(subject.matches?(:foo_parameter => {})).to be(false) end it 'does not match {"foo" => "baz"}' do expect(subject.matches?(:foo_parameter => {"foo" => "baz"})).to be(false) end end context 'with lambda(){"foo"} expected' do subject do block = lambda {|actual| actual == "foo" } described_class.new(:foo_parameter, block, :should) end it 'matches "foo"' do expect(subject.matches?(:foo_parameter => "foo")).to be(true) end it 'does not match nil' do expect(subject.matches?(:foo_parameter => nil)).to be(false) end end context 'with /foo/ expected' do subject do described_class.new(:foo_parameter, /foo/, :should) end it 'matches "foo"' do expect(subject.matches?(:foo_parameter => "foo")).to be(true) end it 'does not match nil' do expect(subject.matches?(:foo_parameter => nil)).to be(false) end end context 'with "foo" expected' do subject do described_class.new(:foo_parameter, "foo", :should) end it 'matches "foo"' do expect(subject.matches?(:foo_parameter => "foo")).to be(true) end it 'does not match nil' do expect(subject.matches?(:foo_parameter => nil)).to be(false) end end end end rspec-puppet-2.6.1/spec/unit/matchers/run_spec.rb000066400000000000000000000077471312614575600220620ustar00rootroot00000000000000require 'spec_helper' describe RSpec::Puppet::FunctionMatchers::Run do let (:wrapper) { double("function wrapper") } before :each do expect(wrapper).to receive(:call).never end it 'should call the wrapper with no params' do expect(wrapper).to receive(:execute).with(no_args).once expect(subject.matches?(wrapper)).to be true end it 'should not match a wrapper that raises an error' do expect(wrapper).to receive(:execute).and_raise(StandardError, 'Forced Error').once expect(subject.matches?(wrapper)).to be false end [ [true], [false], [''], ['string'], [nil], [0], [1.1], [[]], ['one', 'two'], [{}], [{ 'key' => 'value' }], [:undef] ].each do |supplied_params| context "with_params(#{supplied_params.collect { |p| p.inspect }.join(', ')})" do before(:each) { subject.with_params(*supplied_params) } it 'should call the wrapper with the supplied params' do expect(wrapper).to receive(:execute).with(*supplied_params).once expect(subject.matches?(wrapper)).to be true end it 'should not match a wrapper that raises an error' do expect(wrapper).to receive(:execute).and_raise(StandardError, 'Forced Error').once expect(subject.matches?(wrapper)).to be false end end [ true, false, '', 'string', nil, 0, 1.1, [], {}, :undef ].each do |expected_return| context "and_return(#{expected_return.inspect})" do before(:each) { subject.and_return(expected_return) } it 'should match a wrapper that does return the requested value' do expect(wrapper).to receive(:execute).and_return(expected_return).once expect(subject.matches?(wrapper)).to be true end it 'should not match a wrapper that does return a different value' do expect(wrapper).to receive(:execute).and_return(!expected_return).once expect(subject.matches?(wrapper)).to be false end end context "and_raise_error(ArgumentError)" do before(:each) { subject.and_raise_error(ArgumentError) } it 'should match a wrapper that raises ArgumentError' do expect(wrapper).to receive(:execute).and_raise(ArgumentError, 'Forced Error').once expect(subject.matches?(wrapper)).to be true end [ true, false, '', 'string', nil, 0, 1.1, [], {}, :undef ].each do |value| it "should not match a wrapper that returns #{value.inspect}" do expect(wrapper).to receive(:execute).and_return(value).once expect(subject.matches?(wrapper)).to be false end end it 'should not match a wrapper that raises a different error' do expect(wrapper).to receive(:execute).and_raise(StandardError, 'Forced Error').once expect(subject.matches?(wrapper)).to be false end end context "and_raise_error(ArgumentError, /message/)" do before(:each) { subject.and_raise_error(ArgumentError, /message/) } it 'should match a wrapper that raises ArgumentError("with matching message")' do expect(wrapper).to receive(:execute).and_raise(ArgumentError, 'with matching message').once expect(subject.matches?(wrapper)).to be true end it 'should not match a wrapper that raises a different ArgumentError' do expect(wrapper).to receive(:execute).and_raise(ArgumentError, 'Forced Error').once expect(subject.matches?(wrapper)).to be false end [ true, false, '', 'string', nil, 0, 1.1, [], {}, :undef ].each do |value| it "should not match a wrapper that returns #{value.inspect}" do expect(wrapper).to receive(:execute).and_return(value).once expect(subject.matches?(wrapper)).to be false end end it 'should not match a wrapper that raises a different error' do expect(wrapper).to receive(:execute).and_raise(StandardError, 'Forced Error').once expect(subject.matches?(wrapper)).to be false end end end end end rspec-puppet-2.6.1/spec/unit/monkey_patches_spec.rb000066400000000000000000000127521312614575600224510ustar00rootroot00000000000000require 'spec_helper' # rspec 2.x doesn't have RSpec::Support, so fall back to File::ALT_SEPARATOR to # detect if running on windows WINDOWS = defined?(RSpec::Support) ? RSpec::Support::OS.windows? : !!File::ALT_SEPARATOR describe 'File constants' do context 'on windows', :if => WINDOWS do specify('File::PATH_SEPARATOR') { expect(File::PATH_SEPARATOR).to eq(';') } specify('File::ALT_SEPARATOR') { expect(File::ALT_SEPARATOR).to eq("\\") } end context 'on posix', :unless => WINDOWS do specify('File::PATH_SEPARATOR') { expect(File::PATH_SEPARATOR).to eq(':') } specify('File::ALT_SEPARATOR') { expect(File::ALT_SEPARATOR).to be_nil } end end describe 'Pathname constants' do context 'on windows', :if => WINDOWS do specify('Pathname::SEPARATOR_PAT') { expect(Pathname::SEPARATOR_PAT.to_s).to eq(%r{[\\\/]}.to_s) } end context 'on linux', :unless => WINDOWS do specify('Pathname::SEPARATOR_PAT') { expect(Pathname::SEPARATOR_PAT.to_s).to eq(%r{\/}.to_s) } end end # These specs taken from the official ruby spec for File.basename describe 'Pathname#rspec_puppet_basename' do subject { Pathname.new('test') } it 'is not enabled by default' do test_pathname = Pathname.new('test') expect(test_pathname).not_to receive(:rspec_puppet_basename).with(anything) test_pathname.absolute? end context 'when enabled' do before do RSpec.configuration.enable_pathname_stubbing = true end it 'returns the basename of a path (basic cases)' do expect(subject.rspec_puppet_basename('/Some/path/to/test.txt')).to eq('test.txt') expect(subject.rspec_puppet_basename(File.join('/tmp'))).to eq('tmp') expect(subject.rspec_puppet_basename(File.join(*%w( g f d s a b)))).to eq('b') expect(subject.rspec_puppet_basename(File.join('/tmp/'))).to eq('tmp') expect(subject.rspec_puppet_basename('/')).to eq('/') expect(subject.rspec_puppet_basename('//')).to eq('/') expect(subject.rspec_puppet_basename('dir///base///')).to eq('base') expect(subject.rspec_puppet_basename('dir///base')).to eq('base') end it 'returns the last component of the filename' do expect(subject.rspec_puppet_basename('a')).to eq('a') expect(subject.rspec_puppet_basename('/a')).to eq('a') expect(subject.rspec_puppet_basename('/a/b')).to eq('b') expect(subject.rspec_puppet_basename('/ab/ba/bag')).to eq('bag') expect(subject.rspec_puppet_basename('/ab/ba/bag.txt')).to eq('bag.txt') expect(subject.rspec_puppet_basename('/')).to eq('/') end it 'returns a string' do expect(subject.rspec_puppet_basename('foo')).to be_a(String) end it 'returns the basename for unix format' do expect(subject.rspec_puppet_basename('/foo/bar')).to eq('bar') expect(subject.rspec_puppet_basename('/foo/bar.txt')).to eq('bar.txt') expect(subject.rspec_puppet_basename('bar.c')).to eq('bar.c') expect(subject.rspec_puppet_basename('/bar')).to eq('bar') expect(subject.rspec_puppet_basename('/bar/')).to eq('bar') end it 'returns the basename for edgecases' do expect(subject.rspec_puppet_basename('')).to eq('') expect(subject.rspec_puppet_basename('.')).to eq('.') expect(subject.rspec_puppet_basename('..')).to eq('..') end context 'on posix' do before do stub_const('Pathname::SEPARATOR_PAT', /\//) end it 'returns the basename for edgecases' do expect(subject.rspec_puppet_basename('//foo/')).to eq('foo') expect(subject.rspec_puppet_basename('//foo//')).to eq('foo') end it 'takes into consideration the platform path separators' do expect(subject.rspec_puppet_basename('c:\\foo\\bar')).to eq('c:\\foo\\bar') expect(subject.rspec_puppet_basename('c:/foo/bar')).to eq('bar') expect(subject.rspec_puppet_basename('/foo/bar\\baz')).to eq('bar\\baz') end end context 'on windows' do before do stub_const('Pathname::SEPARATOR_PAT', /[\\\/]/) end it 'handles UNC pathnames' do expect(subject.rspec_puppet_basename('baz//foo')).to eq('foo') expect(subject.rspec_puppet_basename('//foo/bar/baz')).to eq('baz') expect(subject.rspec_puppet_basename('\\\\foo\\bar\\baz.txt')).to eq('baz.txt') expect(subject.rspec_puppet_basename('\\\\foo\\bar\\baz')).to eq('baz') end it 'takes into consideration the platform path separators' do expect(subject.rspec_puppet_basename('C:\\foo\\bar')).to eq('bar') expect(subject.rspec_puppet_basename('C:/foo/bar')).to eq('bar') expect(subject.rspec_puppet_basename('/foo/bar\\baz')).to eq('baz') end it 'returns the basename for windows' do expect(subject.rspec_puppet_basename('C:\\foo\\bar\\baz.txt')).to eq('baz.txt') expect(subject.rspec_puppet_basename('C:\\foo\\bar')).to eq('bar') expect(subject.rspec_puppet_basename('C:\\foo\\bar\\')).to eq('bar') expect(subject.rspec_puppet_basename('C:\\foo')).to eq('foo') expect(subject.rspec_puppet_basename('C:\\')).to eq('\\') end it 'returns the basename for windows with forward slash' do expect(subject.rspec_puppet_basename('C:/')).to eq('/') expect(subject.rspec_puppet_basename('C:/foo')).to eq('foo') expect(subject.rspec_puppet_basename('C:/foo/bar')).to eq('bar') expect(subject.rspec_puppet_basename('C:/foo/bar/')).to eq('bar') expect(subject.rspec_puppet_basename('C:/foo/bar//')).to eq('bar') end end end end