def test_with_checksums_partial(tmpdir):
    """with_checksums only calculates checksums of missing types"""

    tmpfile = tmpdir.join("somefile")
    tmpfile.write(b"some data")

    item = PushItem(name="item",
                    src=str(tmpfile),
                    md5sum="1e50210a0202497fb79bc38b6ade6c34")

    hashlib_new = hashlib.new
    computed_types = []

    def patched_hashlib_new(hash_type):
        computed_types.append(hash_type)
        return hashlib_new(hash_type)

    with patch("hashlib.new", new=patched_hashlib_new):
        item_sums = item.with_checksums()

    # with_checksums output should have correct sums
    assert item_sums.md5sum == "1e50210a0202497fb79bc38b6ade6c34"
    assert (item_sums.sha256sum ==
            "1307990e6ba5ca145eb35e99182a9bec46531bc54ddf656a602c780fa0240dee")

    # Only sha256 should have been calculated, since md5 was already present
    assert computed_types == ["sha256"]
예제 #2
0
def test_fields_cached():
    # Try making two items with similar fields.
    # Note: the weird string construction here is meant to defeat
    # the built-in python logic of interning string literals since
    # that would defeat the purpose of the test...
    item1 = PushItem(name="item1",
                     origin="some-origin",
                     dest=["a", "b", "c"],
                     signing_key="a1b2c3d4")
    item2 = PushItem(
        name="item2",
        origin="-".join(["some", "origin"]),
        dest=["a", "b", "c"],
        signing_key="2".join(["a1b", "c3d4"]),
    )

    # Field values should be not only equal...
    for item in (item1, item2):
        assert item.origin == "some-origin"
        assert item.dest == ["a", "b", "c"]
        assert item.signing_key == "A1B2C3D4"

    # ...but they should also be *identical*
    assert item1.origin is item2.origin
    assert item1.dest is item2.dest
    assert item1.signing_key is item2.signing_key
def test_with_checksums_noop():
    """with_checksums does nothing if sums are already present"""
    item = PushItem(
        name="item",
        src="nonexistent-file",
        md5sum="d3b07384d113edec49eaa6238ad5ff00",
        sha256sum=
        "49ae93732fcf8d63fe1cce759664982dbd5b23161f007dba8561862adc96d063",
    )
    assert item.with_checksums() is item
def test_with_checksums_reads_content(tmpdir):
    """with_checksums reads file to calculate checksums"""
    tmpfile = tmpdir.join("somefile")
    tmpfile.write(b"some data")

    item = PushItem(name="item", src=str(tmpfile))
    item_sums = item.with_checksums()

    # Original item should be untouched
    assert not item.md5sum
    assert not item.sha256sum

    # with_checksums output should have correct sums filled in
    assert item_sums.md5sum == "1e50210a0202497fb79bc38b6ade6c34"
    assert (item_sums.sha256sum ==
            "1307990e6ba5ca145eb35e99182a9bec46531bc54ddf656a602c780fa0240dee")
def test_with_checksums_read_fails():
    """with_checksums propagates error if referenced file can't be read"""
    with raises(Exception) as exc_info:
        PushItem(name="item", src="file-does-not-exist").with_checksums()

    # exact type and message is not verified due to py2 vs py3 differences.
    assert "file-does-not-exist" in str(exc_info.value)
def test_pushitem_obj_push():
    """PushItem object passed to the update_push_items works fine."""

    collector = Collector.get("dummy")

    pushitem = PushItem(name="test_pushitem")
    ret_val = collector.update_push_items([pushitem])

    assert ret_val.result() is None
예제 #7
0
def test_partial_with_url_unbound():
    Source.register_backend("returns-url", ReturnsUrlSource)

    # Let's say that I now overwrite this source with an argument (not url) bound
    partial = Source.get_partial("returns-url:", a=123)
    Source.register_backend("returns-url", partial)

    # Then I should be able to obtain an instance of this source, and it
    # should still stuff the path part of the below string into the 'url' arg
    items = [i for i in Source.get("returns-url:/foo/bar?b=88")]

    assert items == [PushItem(name="/foo/bar 123 88")]
예제 #8
0
def test_partial_with_url_bound_overwrite():
    Source.register_backend("returns-url", ReturnsUrlSource)

    # Let's say that I now overwrite this source and I pre-fill a URL
    partial = Source.get_partial("returns-url:", url="/tmp")
    Source.register_backend("returns-url", partial)

    # Then I should be able to obtain an instance of this source, and
    # I can still override the bound URL by passing a new one in the
    # normal manner.
    items = [i for i in Source.get("returns-url:/other/url?a=1&b=2")]

    assert items == [PushItem(name="/other/url 1 2")]
예제 #9
0
def test_partial_with_url_bound():
    Source.register_backend("returns-url", ReturnsUrlSource)

    # Let's say that I now overwrite this source and I pre-fill a URL
    partial = Source.get_partial("returns-url:", url="/tmp")
    Source.register_backend("returns-url", partial)

    # Then I should be able to obtain an instance of this source, with
    # the URL coming from the value previously bound and other arguments
    # still able to be overridden normally.
    items = [i for i in Source.get("returns-url:b=123")]

    assert items == [PushItem(name="/tmp a 123")]
예제 #10
0
def test_empty_push(fake_controller, fake_push, fake_state_path,
                    command_tester, stub_collector):
    """Test a push with no content."""

    # Sanity check that the Pulp server is, initially, empty.
    client = fake_controller.client
    assert list(client.search_content()) == []

    # Set up a pushsource backend which returns no supported items
    Source.register_backend("null", lambda: [PushItem(name="quux")])

    compare_extra = {
        "pulp.yaml": {
            "filename": fake_state_path,
            "normalize": hide_unit_ids,
        }
    }
    args = [
        "",
        "--source",
        "null:",
        "--pulp-url",
        "https://pulp.example.com/",
    ]

    run = functools.partial(entry_point, cls=lambda: fake_push)

    # It should be able to run without crashing.
    command_tester.test(
        run,
        args,
        compare_plaintext=False,
        compare_jsonl=False,
        compare_extra=compare_extra,
    )

    # It should not record any push items at all.
    assert not stub_collector
def test_minimal_pushitem_obj():
    """PushItem object with minimal attributes is translated to
    pushitem dict with destination and checksums as None along
    with other attributes as in the object"""

    mock = Mock()
    Collector.register_backend("mock", lambda: mock)
    collector = Collector.get("mock")

    pushitem = PushItem(name="test_push")
    collector.update_push_items([pushitem])

    update_push_item_args = mock.update_push_items.call_args[0][0]
    assert len(update_push_item_args) == 1
    push_args = update_push_item_args[0]
    assert push_args["filename"] == pushitem.name
    assert push_args["state"] == pushitem.state
    assert push_args["src"] == pushitem.src
    assert push_args["dest"] is None
    assert push_args["checksums"] is None
    assert push_args["origin"] == pushitem.origin
    assert push_args["build"] == pushitem.build
    assert push_args["signing_key"] == pushitem.signing_key
def test_pushitem_obj_attributes():
    """PushItem object attributes are translated and available as expected in
    pushitem dict passed to update_push_items. A pushitem is generated for each
    destination"""

    mock = Mock()
    Collector.register_backend("mock", lambda: mock)
    collector = Collector.get("mock")

    pushitem = PushItem(
        name="test_push",
        origin="some_origin",
        src="source",
        dest=["dest1", "dest2"],
        md5sum="bb1b0d528129f47798006e73307ba7a7",
        sha256sum=
        "4fd23ae44f3366f12f769f82398e96dce72adab8e45dea4d721ddf43fdce31e2",
        build="test_build-1.0.0-1",
        signing_key="FD431D51",
    )
    collector.update_push_items([pushitem])

    update_push_item_args = mock.update_push_items.call_args[0][0]
    assert len(update_push_item_args) == 2
    for i in range(len(update_push_item_args) - 1):
        push_args = update_push_item_args[i]
        assert push_args["filename"] == pushitem.name
        assert push_args["state"] == pushitem.state
        assert push_args["src"] == pushitem.src
        assert push_args["dest"] == pushitem.dest[i]
        assert push_args["checksums"] == {
            "md5": pushitem.md5sum,
            "sha256": pushitem.sha256sum,
        }
        assert push_args["origin"] == pushitem.origin
        assert push_args["build"] == pushitem.build
        assert push_args["signing_key"] == pushitem.signing_key
예제 #13
0
def test_sum_not_string():
    """Can't supply non-string in checksum fields."""

    with raises(TypeError) as exc_info:
        PushItem(name="item", md5sum=1234)
    assert "can't parse 1234 as a hex string" in str(exc_info.value)
예제 #14
0
def test_sum_lower():
    """Valid sums are converted to lowercase."""
    item = PushItem(name="item", md5sum="D3B07384D113EDEC49EAA6238AD5FF00")
    assert item.md5sum == "d3b07384d113edec49eaa6238ad5ff00"
예제 #15
0
def test_sum_bad_chars():
    """Can't supply non hex strings in checksum fields."""
    with raises(ValueError) as exc_info:
        PushItem(name="item", md5sum="fake7384d113edec49eaa6238ad5ff00")
    assert "can't parse" in str(exc_info.value)
예제 #16
0
def test_sum_incomplete():
    """Can't supply truncated value in checksum fields."""
    with raises(ValueError) as exc_info:
        PushItem(name="item", sha256sum="1234abc")
    assert "wrong length" in str(exc_info.value)
예제 #17
0
 def __iter__(self):
     yield PushItem(name="%s %s %s" % (self._url, self._a, self._b))
예제 #18
0
def test_with_checksums_nosrc():
    """with_checksums does nothing on file-less item"""
    item = PushItem(name="item")

    assert item.with_checksums() is item
from pushsource import Source, PushItem

# Just some basic push items for test

ITEMS = [PushItem(name="item1"), PushItem(name="item2")]


class BasicInheritedSource(Source):
    # A source which simply yields some stuff and didn't implement enter/exit
    def __init__(self):
        pass

    def __iter__(self):
        for item in ITEMS:
            yield item


class CustomSource(Source):
    # A more complex source for testing with get_partial and custom enter/exit
    def __init__(self, a, b, c, spy):
        self.a = a
        self.b = b
        self.c = c
        self.spy = spy

    def __enter__(self):
        self.spy.append("enter %s" % ([self.a, self.b, self.c]))
        return self

    def __exit__(self, *_args):
        self.spy.append("exit %s" % ([self.a, self.b, self.c]))