Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use spack.store.use_store consistently in unit tests #21656

Merged
merged 9 commits into from
Feb 18, 2021

Conversation

alalazo
Copy link
Member

@alalazo alalazo commented Feb 12, 2021

#21442 missed a few places in unit tests where the store was monkeypatched within tests. This may cause spurious failures, since monkeypatching was not done consistently over all the global variables in spack.store.

Other modifications:

  • spack.store.use_store has been updated to also swap spack.store.db, spack.store.layout, spack.store.root and spack.store.unpadded_root
  • spack.store.store is serialized in subprocess_context.py on Python > 3.8 + MacOS

@alalazo alalazo added tests General test capability(ies) ci Issues related to Continuous Integration labels Feb 12, 2021
@alalazo alalazo marked this pull request as ready for review February 13, 2021 17:20
@alalazo
Copy link
Member Author

alalazo commented Feb 13, 2021

@tgamblin This is a follow-up on #21442 In that PR I didn't notice we have tests that monkey patch spack.store.*. This is fixed here. Getting tests working correctly on MacOS + Python 3.8+ required serializing also the store, so it would be great if @scheibelp could take a look at least at the last commit in the PR.

Copy link
Member

@tgamblin tgamblin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have one request for comment, and I think @scheibelp should review this.

@@ -1119,7 +1121,6 @@ def relocate_package(spec, allow_root):
prefix_to_prefix_bin = OrderedDict({})

if old_sbang_install_path:
import spack.hooks.sbang as sbang
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There was some kind of circular import issue on certain platforms that led to this being nested here. Can you look at the blame for these nested sbang imports and see if you can figure out whether it's really been resolved? I think @eugeneswalker and @scheibelp should comment.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The imports are still nested, but they are done at the top of the function. This is because imports act like a local assignment to the spack variable and using any spack.* module or function before the nested import will fail with weird errors. Checking git blame right now.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only reference found for these imports #20768 (comment)

@@ -1133,7 +1134,6 @@ def relocate_package(spec, allow_root):
# sbang was a bash script, and it lived in the spack prefix. It is
# now a POSIX script that lives in the install prefix. Old packages
# will have the old sbang location in their shebangs.
import spack.hooks.sbang as sbang
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

see above comment on circular imports.

Spack 0.17.0 Release automation moved this from In progress to Review in progress Feb 16, 2021
Copy link
Member

@scheibelp scheibelp left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have a number of small requests and a larger concern about the consistency of store state when running upstream tests in test/install.py:

This appeared to set store.db and store without addressing the TODO above, so I'm trying to figure out why tests like test_installed_upstream are still passing

I don't have a ready solution for that but we can brainstorm how to deal with it if you'd like.

lib/spack/spack/store.py Outdated Show resolved Hide resolved
lib/spack/spack/test/directory_layout.py Outdated Show resolved Hide resolved
lib/spack/spack/test/directory_layout.py Outdated Show resolved Hide resolved
lib/spack/spack/test/conftest.py Outdated Show resolved Hide resolved
_install('mpileaks ^mpich2')
_install('mpileaks ^zmpi')
_install('externaltest')
_install('mpileaks ^mpich')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is the mock_db.write_transaction call removed here?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As far as I reconstructed, this context manager was used since #2502. Initially it was a way to speed-up the fixture by grabbing a write lock early instead of repeatedly take and release the lock for each installation (like Spack would do in its normal operations). This made sense since database or mutable_database were installing and uninstalling specs at least once per python file. Since some time though the installations are done just once per session, moved to a cache directory and copied wherever they are needed without the additional burden of installing and uninstalling them again. All this is just to say that we will not lose anything in terms of test performance by removing the context manager.

Instead, the necessity to remove it in this PR comes from the additional serialization I do of attributes related to the store. When we fork a process and we _serialize we create an equivalent, but different, store object in the forked process. If a write lock for the same DB is held by the parent process that will prevent the child to proceed.

lib/spack/spack/test/config_values.py Show resolved Hide resolved
lib/spack/spack/subprocess_context.py Outdated Show resolved Hide resolved
spack#21442 missed a few places in unit tests where the store
was monkeypatched within tests. This may cause spurious
failures, since monkeypatching was not done consistently
over all the global variables in spack.store

The spack.store.use_store context manager has been updated
to also swap spack.db, spack.layout, spack.root and
spack.unpadded_root consistently
- Set store attributes on different lines
- Add a comment explaining the call to _store()
Before this commit there were local fixtures
replicating the same behavior of creating a
temporary local store.
- Add a comment explaining the call to _store()
- Use temporary_store in install_mockery
Copy link
Member

@scheibelp scheibelp left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this refactor is looking excellent. Especially if we can remove all calls which monkeypatch either the store or db, i.e. all calls like:

monkeypatch.setattr(spack.store, 'db'
monkeypatch.setattr(spack.store, 'store'

I think all such calls have been handled at this point. Calls like

monkeypatch.setattr(spack.store.layout, 'build_packages_path', bpp_path)

should be fine.

I have a couple additional requests related to documentation

temporary_store_path = tmpdir.join('opt')
with spack.store.use_store(str(temporary_store_path)) as s:
yield s
temporary_store_path.remove()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it necessary to remove this? I'd assume the tmpdir fixture would handle that for you. If it needs to happen, I think it should happen outside of the context manager.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's one test in bindist.py that fails without this line, so I moved it outside of the context manager. We can investigate in a later PR why the test is failing. For what is worth I was under the impression that the tmpdir had to be cleanup immediately after a succesful test, but it seems a few of them are kept around at any time, see e.g. here

lib/spack/spack/test/install.py Show resolved Hide resolved
- Moved tmpdir path removal outside of
  context manager
- Added docstring for install_upstream
Copy link
Member

@scheibelp scheibelp left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have a final request regarding how the Store object is serialized. I think this is good to go after that. Do you agree with the following commit message:

Testing: use spack.store.use_store everywhere (#21656)

Keep spack.store.store and spack.store.db consistent in unit tests

* Remove calls to monkeypatch for spack.store.store and spack.store.db:
  tests that used these called one or the other, which lead to
  inconsistencies (the tests passed regardless but were fragile as a
  result)
* Fixtures making use of monkeypatch with mock_store now use the
  updated use_store function, which sets store.store and store.db
  consistently
* subprocess_context.TestState now transfers the serializes and
  restores spack.store.store (without the monkeypatch changes this
  would have created inconsistencies)

lib/spack/spack/store.py Show resolved Hide resolved
lib/spack/spack/subprocess_context.py Outdated Show resolved Hide resolved
@alalazo
Copy link
Member Author

alalazo commented Feb 18, 2021

The commit message is great, I completely agree with that.

@scheibelp scheibelp dismissed tgamblin’s stale review February 18, 2021 21:15

Request for comment has been addressed

@scheibelp scheibelp merged commit f2e3edf into spack:develop Feb 18, 2021
Spack 0.17.0 Release automation moved this from Review in progress to Done Feb 18, 2021
@scheibelp
Copy link
Member

Thanks!

@alalazo alalazo deleted the fixes/spack_store_use_store branch February 18, 2021 21:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
ci Issues related to Continuous Integration tests General test capability(ies)
Projects
No open projects
Development

Successfully merging this pull request may close these issues.

None yet

3 participants