Skip to content

Conversation

@Iristyle
Copy link
Contributor

This supercedes #5041 with some changes to commits / commit messages

DLuCJ added 3 commits July 13, 2016 08:25
Executing parallel specs on Windows is not reliable in part, because
the module tool shares file system state across specs.  Previously,
executing `rake parallel:spec` on Windows would fail, even when passing
on other platforms.

This commit is one of several that will allow specs to be executed in
parallel by:

* Fixing colliding directory read/writes in installer_spec and
  upgrader_spec by stubbing Puppet.settings[:module_working_dir]
  to a new directory before each test in installer_spec and in
  upgrader_spec. This issue only appears when running these tests
  concurrently

  unpacker_spec was changed to follow a similar pattern due to
  discussion about Puppet settings maybe becoming immutable after
  first load in the future.
Executing parallel specs on Windows is not reliable in part, because
of how specs define Puppet::Util::Plist on platforms that don't have
cfpropertylist support.  Previously, executing `rake parallel:spec` on
Windows would fail, even when passing on other platforms.

This commit is one of several that will allow specs to be executed in
parallel by:

 * Moving the cfpropertylist code guards from tests to plist.rb, so that
   any code may require 'util/plist' even if the current platform does
   not have cfpropertylist support (detectable via
   Puppet.features.cfpropertylist?).

   This has the benefit of removing definitions of Puppet::Util::Plist
   from specs designed to run on all platforms. Previously pkgdmg,
   launchd tests required Puppet::Util::Plist to be explicitly declared
   inside the specs to be able to execute on platforms without
   cfpropertylist support - which could cause a race when run in
   parallel.

   Note that prior to this, spec\unit\provider\service\launchd_spec.rb
   and spec\unit\provider\package\appdmg_spec.rb could not be run in
   isolation on Windows
On Windows, $CHILD_STATUS is nil while the tests in
spec/unit/provider/service/*.rb. and pkg_spec are running.
This results in a "Can't modify frozen object"
runtime error.  However, the tests are able to pass
when run serially with the tests in capability_spec, for
example. The reason being, some tests in capability_spec
make a compile_to_catalog() call which, as a side
effect, generates a pid.  $CHILD_STATUS is able to
latch on to this pid, resolving the issue.

The bug shows up when the tests are run in isolation or in
parallel (on occasion, when the tests are grouped in
such a way and executed in such an order that
$CHILD_STATUS is not properly set by another test before
these tests run).

This commit makes the following changes:

* Replaces $CHILD_STATUS.exitstatus calls with stubbed / mocked
    Puppet::Util::Execution.exitstatus calls in execution_spec
    and pacman_spec

* In the other specs, it generates a pid for $CHILD_STATUS by
    spinning up a process.

    The previous strategy does not work for these files because
    they call into $CHILD_STATUS in lib/provider files, not just
    in the specs. And, Puppet::Util::Execution.exitstatus is a
    private class method, so that it  is not possible to outright
    replace these $CHILD_STATUS.exitstatus calls.  This may be
    resolved with some refactoring in the future.

    Also, require 'English' does not set $CHILD_STATUS on
    Windows as it does on other platforms.  After requiring,
    $CHILD_STATUS (and $?) is still nil.
@puppetcla
Copy link

CLA signed by all contributors.

@Iristyle
Copy link
Contributor Author

When running parallel specs, I'm seeing a few fails, but that may be related to perf issues on my VM? Seen these FiberError messages before @DLuCJ ?

Failures:

  1) the Puppet::Pops::Serialization over Puppet::Pops::Serialization::JSON can write
and read a parameterized Variant
     Failure/Error: ext_no = ext_etor.next
     FiberError:
       can't create fiber
     # ./lib/puppet/pops/serialization/json.rb:233:in `next'
     # ./lib/puppet/pops/serialization/json.rb:233:in `read'
     # ./lib/puppet/pops/serialization/abstract_reader.rb:38:in `read'
     # ./lib/puppet/pops/serialization/deserializer.rb:23:in `read'
     # ./lib/puppet/pops/serialization/deserializer.rb:31:in `block in read'
     # ./lib/puppet/pops/serialization/deserializer.rb:31:in `times'
     # ./lib/puppet/pops/serialization/deserializer.rb:31:in `read'
     # ./lib/puppet/pops/serialization/object.rb:21:in `block in read'
     # ./lib/puppet/pops/serialization/object.rb:21:in `initialize'
     # ./lib/puppet/pops/serialization/object.rb:21:in `new'
     # ./lib/puppet/pops/serialization/object.rb:21:in `read'
     # ./lib/puppet/pops/types/p_object_type.rb:392:in `read'
     # ./lib/puppet/pops/serialization/deserializer.rb:41:in `read'
     # ./spec/unit/pops/serialization/serialization_spec.rb:33:in `read'
     # ./spec/unit/pops/serialization/serialization_spec.rb:158:in `block (5 levels) i
n <module:Serialization>'
     # ./spec/unit/pops/serialization/serialization_spec.rb:19:in `block (4 levels) in
 <module:Serialization>'
     # ./lib/puppet/context.rb:65:in `override'
     # ./lib/puppet.rb:240:in `override'
     # ./spec/unit/pops/serialization/serialization_spec.rb:18:in `block (3 levels) in
 <module:Serialization>'
     # util/rspec_runner:39:in `run'
     # util/rspec_runner:53:in `<main>'
  2) the Puppet::Pops::Serialization over Puppet::Pops::Serialization::JSON can write
and read a parameterized Object
     Failure/Error: obj = etor.next
     FiberError:
       can't create fiber
     # ./lib/puppet/pops/serialization/json.rb:224:in `next'
     # ./lib/puppet/pops/serialization/json.rb:224:in `block in read'
     # ./lib/puppet/pops/serialization/json.rb:220:in `loop'
     # ./lib/puppet/pops/serialization/json.rb:220:in `read'
     # ./lib/puppet/pops/serialization/abstract_reader.rb:38:in `read'
     # ./lib/puppet/pops/serialization/deserializer.rb:23:in `read'
     # ./spec/unit/pops/serialization/serialization_spec.rb:33:in `read'
     # ./spec/unit/pops/serialization/serialization_spec.rb:166:in `block (5 levels) i
n <module:Serialization>'
     # ./spec/unit/pops/serialization/serialization_spec.rb:19:in `block (4 levels) in
 <module:Serialization>'
     # ./lib/puppet/context.rb:65:in `override'
     # ./lib/puppet.rb:240:in `override'
     # ./spec/unit/pops/serialization/serialization_spec.rb:18:in `block (3 levels) in
 <module:Serialization>'
     # util/rspec_runner:39:in `run'
     # util/rspec_runner:53:in `<main>'
  3) the Puppet::Pops::Serialization over Puppet::Pops::Serialization::JSON can write
and read an AST model Locator
     Failure/Error: obj = etor.next
     FiberError:
       can't create fiber
     # ./lib/puppet/pops/serialization/json.rb:224:in `next'
     # ./lib/puppet/pops/serialization/json.rb:224:in `block in read'
     # ./lib/puppet/pops/serialization/json.rb:220:in `loop'
     # ./lib/puppet/pops/serialization/json.rb:220:in `read'
     # ./lib/puppet/pops/serialization/abstract_reader.rb:38:in `read'
     # ./lib/puppet/pops/serialization/deserializer.rb:23:in `read'
     # ./spec/unit/pops/serialization/serialization_spec.rb:33:in `read'
     # ./spec/unit/pops/serialization/serialization_spec.rb:176:in `block (5 levels) i
n <module:Serialization>'
     # ./spec/unit/pops/serialization/serialization_spec.rb:19:in `block (4 levels) in
 <module:Serialization>'
     # ./lib/puppet/context.rb:65:in `override'
     # ./lib/puppet.rb:240:in `override'
     # ./spec/unit/pops/serialization/serialization_spec.rb:18:in `block (3 levels) in
 <module:Serialization>'
     # util/rspec_runner:39:in `run'
     # util/rspec_runner:53:in `<main>'
  4) the Puppet::Pops::Serialization over Puppet::Pops::Serialization::JSON can write
and read an AST model nested Expression
     Failure/Error: obj = etor.next
     FiberError:
       can't create fiber
     # ./lib/puppet/pops/serialization/json.rb:224:in `next'
     # ./lib/puppet/pops/serialization/json.rb:224:in `block in read'
     # ./lib/puppet/pops/serialization/json.rb:220:in `loop'
     # ./lib/puppet/pops/serialization/json.rb:220:in `read'
     # ./lib/puppet/pops/serialization/abstract_reader.rb:38:in `read'
     # ./lib/puppet/pops/serialization/deserializer.rb:23:in `read'
     # ./spec/unit/pops/serialization/serialization_spec.rb:33:in `read'
     # ./spec/unit/pops/serialization/serialization_spec.rb:196:in `block (5 levels) i
n <module:Serialization>'
     # ./spec/unit/pops/serialization/serialization_spec.rb:19:in `block (4 levels) in
 <module:Serialization>'
     # ./lib/puppet/context.rb:65:in `override'
     # ./lib/puppet.rb:240:in `override'
     # ./spec/unit/pops/serialization/serialization_spec.rb:18:in `block (3 levels) in
 <module:Serialization>'
     # util/rspec_runner:39:in `run'
     # util/rspec_runner:53:in `<main>'
  5) the Puppet::Pops::Serialization over Puppet::Pops::Serialization::JSON When debug
ging can write and read an AST expression
     Failure/Error: obj = etor.next
     FiberError:
       can't create fiber
     # ./lib/puppet/pops/serialization/json.rb:224:in `next'
     # ./lib/puppet/pops/serialization/json.rb:224:in `block in read'
     # ./lib/puppet/pops/serialization/json.rb:220:in `loop'
     # ./lib/puppet/pops/serialization/json.rb:220:in `read'
     # ./lib/puppet/pops/serialization/abstract_reader.rb:38:in `read'
     # ./lib/puppet/pops/serialization/deserializer.rb:23:in `read'
     # ./spec/unit/pops/serialization/serialization_spec.rb:33:in `read'
     # ./spec/unit/pops/serialization/serialization_spec.rb:221:in `block (4 levels) i
n <module:Serialization>'
     # ./spec/unit/pops/serialization/serialization_spec.rb:19:in `block (4 levels) in
 <module:Serialization>'
     # ./lib/puppet/context.rb:65:in `override'
     # ./lib/puppet.rb:240:in `override'
     # ./spec/unit/pops/serialization/serialization_spec.rb:18:in `block (3 levels) in
 <module:Serialization>'
     # util/rspec_runner:39:in `run'
     # util/rspec_runner:53:in `<main>'
Finished in 1 minute 9 seconds (files took 9.35 seconds to load)

  1) Puppet::SSL::CertificateFactory when generating the certificate should add subjec
tAltName when the CSR requests them
     Failure/Error: if rf.flock(::File::LOCK_EX|::File::LOCK_NB)
     fatal:
       failed to launch waiter thread:1455
     # ./lib/puppet/file_system/file_impl.rb:51:in `flock'
     # ./lib/puppet/file_system/file_impl.rb:51:in `block in exclusive_open'
     # ./lib/puppet/file_system/file_impl.rb:50:in `open'
     # ./lib/puppet/file_system/file_impl.rb:50:in `exclusive_open'
     # ./lib/puppet/file_system.rb:110:in `exclusive_open'
     # ./lib/puppet/settings/file_setting.rb:190:in `block in exclusive_open'
     # ./lib/puppet/settings/file_setting.rb:231:in `block (2 levels) in controlled_ac
cess'
     # ./lib/puppet/util.rb:142:in `withumask'
     # ./lib/puppet/settings/file_setting.rb:221:in `block in controlled_access'
     # ./lib/puppet/util/suidmanager.rb:64:in `asuser'
     # ./lib/puppet/settings/file_setting.rb:219:in `controlled_access'
     # ./lib/puppet/settings/file_setting.rb:189:in `exclusive_open'
     # ./lib/puppet/ssl/certificate_authority.rb:215:in `next_serial'
     # ./lib/puppet/ssl/certificate_authority.rb:301:in `sign'
     # ./lib/puppet/ssl/certificate_authority.rb:148:in `generate_ca_certificate'
     # ./spec/unit/ssl/certificate_factory_spec.rb:18:in `block (2 levels) in <top (re
quired)>'
     # ./spec/unit/ssl/certificate_factory_spec.rb:131:in `block (3 levels) in <top (r
equired)>'
     # util/rspec_runner:39:in `run'
     # util/rspec_runner:53:in `<main>'
Finished in 1 minute 2.34 seconds (files took 17.69 seconds to load)

Finished in 14 minutes 46 seconds
20425 examples, 6 failures, 52 pending

Failed examples:
rspec ./spec/unit/pops/serialization/serialization_spec.rb:155 # the Puppet::Pops::Ser
ialization over Puppet::Pops::Serialization::JSON can write and read a parameterized V
ariant
rspec ./spec/unit/pops/serialization/serialization_spec.rb:163 # the Puppet::Pops::Ser
ialization over Puppet::Pops::Serialization::JSON can write and read a parameterized O
bject
rspec ./spec/unit/pops/serialization/serialization_spec.rb:173 # the Puppet::Pops::Ser
ialization over Puppet::Pops::Serialization::JSON can write and read an AST model Loca
tor
rspec ./spec/unit/pops/serialization/serialization_spec.rb:181 # the Puppet::Pops::Ser
ialization over Puppet::Pops::Serialization::JSON can write and read an AST model nest
ed Expression
rspec ./spec/unit/pops/serialization/serialization_spec.rb:206 # the Puppet::Pops::Ser
ialization over Puppet::Pops::Serialization::JSON When debugging can write and read an
 AST expression
rspec ./spec/unit/ssl/certificate_factory_spec.rb:120 # Puppet::SSL::CertificateFactor
y when generating the certificate should add subjectAltName when the CSR requests them

@Iristyle Iristyle force-pushed the pr/5041 branch 2 times, most recently from 620ded4 to 33465f9 Compare July 13, 2016 22:28
Executing parallel specs on Windows is not reliable in part, because
the Puppet type system must have been initialized prior to these
settings specs running, which may not be the case when run parallel.
Executing `rake parallel:spec` on Windows would fail, even when
passing on other platforms.

This commit is one of several that will allow specs to be executed in
parallel.

* With Puppet.features.microsoft_windows? stubbed to return false the
  first time a settings catalog is built, it will autorequire the
  user, file and group type class definitions.  When doing this, it
  triggers a URI building call through Puppet::Util.path_to_uri to
  specify a full path to the actual type implementation code from
  puppet/type/{file,user,group}.rb

  So when run in isolation, prior to this commit, 3 tests would fail
  as a result of this process because it would try to use invalid
  non-Windows path to load files.

  However, when this test is run after other tests that have loaded
  the user / group / file types, then there is no problem as the stub
  doesn't impact load behavior.

  This fix also addresses being able to run these specs parallel
@Iristyle Iristyle merged commit ad7607e into puppetlabs:master Jul 13, 2016
@Iristyle Iristyle deleted the pr/5041 branch July 13, 2016 22:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants