Merge lp:~benji/landscape-client/bug-1548946-xenial-test-failures into lp:~landscape/landscape-client/trunk

Proposed by Benji York
Status: Merged
Approved by: Benji York
Approved revision: 834
Merged at revision: 832
Proposed branch: lp:~benji/landscape-client/bug-1548946-xenial-test-failures
Merge into: lp:~landscape/landscape-client/trunk
Diff against target: 102 lines (+27/-13)
2 files modified
landscape/package/tests/helpers.py (+1/-1)
landscape/package/tests/test_facade.py (+26/-12)
To merge this branch: bzr merge lp:~benji/landscape-client/bug-1548946-xenial-test-failures
Reviewer Review Type Date Requested Status
Chris Glass (community) Approve
Free Ekanayaka (community) Approve
Review via email: mp+288180@code.launchpad.net

Commit message

This branch fixes two test failures and one non-failure on Xenial.

The simplest failure was a simple difference in deb stanza ordering
that caused a failure of test_get_package_stanza. I changed the test
to store the stanzas in sets and compared those instead so as to be
order-agnostic.

The next failure was caused by a change in the way the apt cache works.
The test_reload_channels_not_refetch_package_index test was using a
change in package visibility to the apt cache to tell when the cache's
update() method had been called. The cache behaviour has changed so
that package existance changes are now reflected earlier than before.
Therefore, I added a test-only subclass of the cache which records the
fact that it's update method has been called, which is the operative
piece of information for the test.

The change to the cache behaviour also meant that
test_reload_channels_force_reload_binaries would pass even if the call
to update() were removed, so I used the cache subclass in that test as
well.

Description of the change

This branch fixes two test failures and one non-failure on Xenial.

The simplest failure was a simple difference in deb stanza ordering
that caused a failure of test_get_package_stanza. I changed the test
to store the stanzas in sets and compared those instead so as to be
order-agnostic.

The next failure was caused by a change in the way the apt cache works.
The test_reload_channels_not_refetch_package_index test was using a
change in package visibility to the apt cache to tell when the cache's
update() method had been called. The cache behaviour has changed so
that package existance changes are now reflected earlier than before.
Therefore, I added a test-only subclass of the cache which records the
fact that it's update method has been called, which is the operative
piece of information for the test.

The change to the cache behaviour also meant that
test_reload_channels_force_reload_binaries would pass even if the call
to update() were removed, so I used the cache subclass in that test as
well.

Testing instructions:

Before this branch running

    trial landscape.package.tests.test_facade.AptFacadeTest

would result in failing tests. Now it shouldn't.

To ensure the test that never failed before will actually fail, remove
or comment out the calls to self._cache.update() in
landscape/package/facade.py and invoke this test run:

    trial landscape.package.tests.test_facade.AptFacadeTest.test_reload_channels_force_reload_binaries

To post a comment you must log in.
832. By Benji York

Fix tests

Revision history for this message
Free Ekanayaka (free.ekanayaka) wrote :

I'm basically +1 with a non-blocking nitpick.

Just marking as Needs information because of the following question.

Since it seems you investigated the issue in depth and possible looked at the changed behavior in the apt module, do you think it would be possible to avoid using the TestCache and change the test to adapt to the new behavior somehow? Or is it now plain impossible for calling code to have visibility on that?

review: Needs Information
Revision history for this message
Benji York (benji) wrote :

> I'm basically +1 with a non-blocking nitpick.
>
> Just marking as Needs information because of the following question.
>
> Since it seems you investigated the issue in depth and possible looked at the
> changed behavior in the apt module, do you think it would be possible to avoid
> using the TestCache and change the test to adapt to the new behavior somehow?
> Or is it now plain impossible for calling code to have visibility on that?

I spent a (timeboxed) bit of time trying to discern exactly how the cache's behaviour has changed, and I couldn't figure enough out to exploit it for our tests.

Arguably, exploiting said details is what got us into this situation, but I wouldn't argue that too strenuously.

Revision history for this message
Benji York (benji) :
833. By Benji York

switch from comparing sets to comparing lists in an order-independent way

Revision history for this message
Free Ekanayaka (free.ekanayaka) wrote :

> > I'm basically +1 with a non-blocking nitpick.
> >
> > Just marking as Needs information because of the following question.
> >
> > Since it seems you investigated the issue in depth and possible looked at
> the
> > changed behavior in the apt module, do you think it would be possible to
> avoid
> > using the TestCache and change the test to adapt to the new behavior
> somehow?
> > Or is it now plain impossible for calling code to have visibility on that?
>
> I spent a (timeboxed) bit of time trying to discern exactly how the cache's
> behaviour has changed, and I couldn't figure enough out to exploit it for our
> tests.
>
> Arguably, exploiting said details is what got us into this situation, but I
> wouldn't argue that too strenuously.

Right, has all integration-level tests they have a cost and they get to failure situations when the other party changes, but flip side is that they increase confidence in the behavior of the external system (the apt python library in this case) and the way your code in interacts with it.

I'm approving this branch, but I'd suggest to file a bug about this and put an # XXX comment pointing to the bug inside the class docstring of the newly introduced TestCache.

+1

review: Approve
Revision history for this message
Free Ekanayaka (free.ekanayaka) wrote :

> > > I'm basically +1 with a non-blocking nitpick.
> > >
> > > Just marking as Needs information because of the following question.
> > >
> > > Since it seems you investigated the issue in depth and possible looked at
> > the
> > > changed behavior in the apt module, do you think it would be possible to
> > avoid
> > > using the TestCache and change the test to adapt to the new behavior
> > somehow?
> > > Or is it now plain impossible for calling code to have visibility on that?
> >
> > I spent a (timeboxed) bit of time trying to discern exactly how the cache's
> > behaviour has changed, and I couldn't figure enough out to exploit it for
> our
> > tests.
> >
> > Arguably, exploiting said details is what got us into this situation, but I
> > wouldn't argue that too strenuously.
>
> Right, has all integration-level tests they have a cost and they get to
> failure situations when the other party changes, but flip side is that they
> increase confidence in the behavior of the external system (the apt python
> library in this case) and the way your code in interacts with it.
>
> I'm approving this branch, but I'd suggest to file a bug about this and put an
> # XXX comment pointing to the bug inside the class docstring of the newly
> introduced TestCache.
>
> +1

Ideally the class docstring of TestCache should also explain the background of why it was introduced, summarizing the content of the bug its pointing to (in case one wants to get the full context).

834. By Benji York

add docstring describing the origin of a test helper

Revision history for this message
Chris Glass (tribaal) wrote :

+1!

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'landscape/package/tests/helpers.py'
2--- landscape/package/tests/helpers.py 2015-03-03 14:16:05 +0000
3+++ landscape/package/tests/helpers.py 2016-03-11 12:06:26 +0000
4@@ -86,7 +86,7 @@
5 version=version, control_fields=control_fields)
6
7 def _touch_packages_file(self, deb_dir):
8- """Make sure the Packages file get a newer mtime value.
9+ """Make sure the Packages file gets a newer mtime value.
10
11 If we rely on simply writing to the file to update the mtime, we
12 might end up with the same as before, since the resolution is
13
14=== modified file 'landscape/package/tests/test_facade.py'
15--- landscape/package/tests/test_facade.py 2015-04-15 13:16:20 +0000
16+++ landscape/package/tests/test_facade.py 2016-03-11 12:06:26 +0000
17@@ -3,6 +3,7 @@
18 import textwrap
19 import tempfile
20
21+import apt
22 import apt_pkg
23 from apt.package import Package
24 from aptsources.sourceslist import SourcesList
25@@ -43,6 +44,23 @@
26 self.description = description
27
28
29+class TestCache(apt.cache.Cache):
30+ """An apt cache wrapper which we can tell has been updated.
31+
32+ When updating the client to work with Xenial, apt.cache.Cache behaviour
33+ which tests depended on changed in such a way that we could no longer
34+ easily tell from the outside if the cache had been updated or not. This
35+ wrapper was introduced to regain that ability. See bug 1548946 for more
36+ information.
37+ """
38+
39+ _update_called = False
40+
41+ def update(self):
42+ self._update_called = True
43+ return super(TestCache, self).update()
44+
45+
46 class AptFacadeTest(LandscapeTest):
47
48 helpers = [AptFacadeHelper, EnvironSaverHelper]
49@@ -267,10 +285,10 @@
50 deb_dir = self.makeDir()
51 create_deb(deb_dir, PKGNAME1, PKGDEB1)
52 deb_file = os.path.join(deb_dir, PKGNAME1)
53- stanza = self.facade.get_package_stanza(deb_file)
54+ stanza = self.facade.get_package_stanza(deb_file).split("\n")
55 SHA256 = (
56 "f899cba22b79780dbe9bbbb802ff901b7e432425c264dc72e6bb20c0061e4f26")
57- self.assertEqual(textwrap.dedent("""\
58+ self.assertItemsEqual(textwrap.dedent("""\
59 Package: name1
60 Priority: optional
61 Section: Group1
62@@ -291,7 +309,7 @@
63 SHA256: %(sha256)s
64 Description: Summary1
65 Description1
66- """ % {"filename": PKGNAME1, "sha256": SHA256}),
67+ """ % {"filename": PKGNAME1, "sha256": SHA256}).split("\n"),
68 stanza)
69
70 def test_add_channel_deb_dir_creates_packages_file(self):
71@@ -418,14 +436,12 @@
72 self.facade.add_channel_apt_deb("file://%s" % deb_dir, "./")
73 self.facade.reload_channels()
74 new_facade = AptFacade(root=self.apt_root)
75- self._add_package_to_deb_dir(deb_dir, "bar")
76+ self._add_package_to_deb_dir(deb_dir, "foo", version="2.0")
77 self._touch_packages_file(deb_dir)
78 new_facade.refetch_package_index = False
79+ new_facade._cache = TestCache(rootdir=new_facade._root)
80 new_facade.reload_channels()
81- self.assertEqual(
82- ["foo"],
83- sorted(version.package.name
84- for version in new_facade.get_packages()))
85+ self.assertFalse(new_facade._cache._update_called)
86
87 def test_reload_channels_force_reload_binaries(self):
88 """
89@@ -440,11 +456,9 @@
90 self._add_package_to_deb_dir(deb_dir, "bar")
91 self._touch_packages_file(deb_dir)
92 self.facade.refetch_package_index = False
93+ self.facade._cache = TestCache(rootdir=self.facade._root)
94 self.facade.reload_channels(force_reload_binaries=True)
95- self.assertEqual(
96- ["bar", "foo"],
97- sorted(version.package.name
98- for version in self.facade.get_packages()))
99+ self.assertTrue(self.facade._cache._update_called)
100
101 def test_reload_channels_no_force_reload_binaries(self):
102 """

Subscribers

People subscribed via source and target branches

to all changes: