def test_unregister_resets_default(): """Unregistering a backend unsets it as the default backend (if it was set).""" class CountingCollector(object): CONSTRUCTED_COUNT = 0 def __init__(self): CountingCollector.CONSTRUCTED_COUNT += 1 Collector.register_backend("counter", CountingCollector) Collector.set_default_backend("counter") # Calling get() should construct custom backend once. Collector.get() assert CountingCollector.CONSTRUCTED_COUNT == 1 # Calling get() should construct custom backend again. Collector.get() assert CountingCollector.CONSTRUCTED_COUNT == 2 Collector.register_backend("counter", None) # Calling get() after unregister should succeed assert Collector.get() # And it should not have constructed the custom backend assert CountingCollector.CONSTRUCTED_COUNT == 2
def test_set_default(): """Can set and use a default collector.""" class MyCollector(object): INSTANCES = [] def __init__(self): MyCollector.INSTANCES.append(self) self.pushed = [] def update_push_items(self, items): self.pushed.extend(items) Collector.register_backend("my-collector", MyCollector) Collector.set_default_backend("my-collector") items = [ { "filename": "file1", "state": "PENDING" }, { "filename": "file2", "state": "PENDING" }, ] # Updating push items through default collector should succeed Collector.get().update_push_items(items).result() # It should have used the class we installed as the default assert len(MyCollector.INSTANCES) == 1 assert MyCollector.INSTANCES[0].pushed == items
def reset_backend(): """Resets the default backend both before and after each test, and clears my-collector backend. """ Collector.set_default_backend(None) yield Collector.set_default_backend(None) Collector.register_backend("my-collector", None)
def test_base_class_context_manager(): """Exercise the __enter__ and __exit__ methods of Collector.""" collector = Collector() # use my-collector name because the autouse fixture `reset_backend` # will clean it up for us Collector.register_backend("my-collector", lambda: collector) Collector.set_default_backend("my-collector") # empty with just to exercise __enter__ and __exit__ with Collector.get(): pass
def test_context_manager_backend(): """Test a backend's context manager protocol methods are called properly.""" collector = MagicMock(spec=Collector) # use my-collector name because the autouse fixture `reset_backend` # will clean it up for us Collector.register_backend("my-collector", lambda: collector) Collector.set_default_backend("my-collector") with Collector.get(): pass collector.__enter__.assert_called_once() collector.__exit__.assert_called_once_with(*(None, ) * 3)
def fake_collector(): """Install fake in-memory backend for pushcollector library. Recorded push items can be tested via this instance. This is an autouse fixture so that all tests will automatically use the fake backend. """ collector = FakeCollector() Collector.register_backend("pubtools-pulp-test", lambda: collector) Collector.set_default_backend("pubtools-pulp-test") yield collector Collector.set_default_backend(None)
def stub_collector(): """Installs a custom pushcollector backend which records all push items onto a plain old list. Yields the list; it can be inspected to see which push items were recorded.""" itemlist = [] Collector.register_backend("pubtools-pulp-test", lambda: StubCollector(itemlist)) Collector.set_default_backend("pubtools-pulp-test") yield itemlist Collector.set_default_backend(None) Collector.register_backend("pubtools-pulp-test", None)
def test_always_returns_future(): """Collector interface returns futures regardless of backend return type.""" return_value = None class TestCollector(object): def update_push_items(self, items): return return_value def attach_file(self, filename, content): return return_value def append_file(self, filename, content): return return_value Collector.register_backend("test", TestCollector) collector = Collector.get("test") # If backend returns a successful future (of any value), # interface returns an empty future return_value = f_return("abc") assert collector.update_push_items([]).result() is None assert collector.attach_file("somefile", "").result() is None assert collector.append_file("somefile", "").result() is None # If backend returns a failed future, # interface returns a failed future with error propagated error = RuntimeError("oops") return_value = f_return_error(error) assert collector.update_push_items([]).exception() is error assert collector.attach_file("somefile", "").exception() is error assert collector.append_file("somefile", "").exception() is error # If backend returns a non-future, # interface returns an empty future return_value = "abc" assert collector.update_push_items([]).result() is None assert collector.attach_file("somefile", "").result() is None assert collector.append_file("somefile", "").result() is None
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
def test_register_backend_wrong_type(): """register_backend raises TypeError if passed incorrect type""" with pytest.raises(TypeError): Collector.register_backend("my-colletor", Collector())