def test_upload_polls_status(client_mock, caplog, config): """Upload polls status url until the end is indicated.""" caplog.set_level(logging.DEBUG, logger="charmcraft.commands") store = Store(config.charmhub) # first and second response, for pushing bytes and let the store know about it test_upload_id = "test-upload-id" client_mock.push.return_value = test_upload_id test_status_url = "https://store.c.c/status" client_mock.post.return_value = {"status-url": test_status_url} # the status checking response, will answer something not done yet twice, then ok test_revision = 123 test_status_ok = "test-status" status_response_1 = { "revisions": [{"status": "still-scanning", "revision": None, "errors": None}] } status_response_2 = { "revisions": [{"status": "more-revisions", "revision": None, "errors": None}] } status_response_3 = { "revisions": [ {"status": test_status_ok, "revision": test_revision, "errors": None} ] } client_mock.get.side_effect = [ status_response_1, status_response_2, status_response_3, ] test_status_resolution = "clean and crispy" fake_statuses = {test_status_ok: test_status_resolution} with patch.dict( "charmcraft.commands.store.store.UPLOAD_ENDING_STATUSES", fake_statuses ): with patch("charmcraft.commands.store.store.POLL_DELAY", 0.01): result = store._upload("/test/endpoint/", "some-filepath") # check the status-checking client calls (kept going until third one) assert client_mock.mock_calls[2:] == [ call.get(test_status_url), call.get(test_status_url), call.get(test_status_url), ] # check result which must have values from final result assert result.ok == test_status_resolution assert result.status == test_status_ok assert result.revision == test_revision # check logs expected = [ "Upload test-upload-id started, got status url https://store.c.c/status", "Status checked: " + str(status_response_1), "Status checked: " + str(status_response_2), "Status checked: " + str(status_response_3), ] assert expected == [rec.message for rec in caplog.records]
def test_upload_including_extra_parameters(client_mock, caplog, config): """Verify that the upload includes extra parameters if given.""" caplog.set_level(logging.DEBUG, logger="charmcraft.commands") store = Store(config.charmhub) # the first response, for when pushing bytes test_upload_id = "test-upload-id" client_mock.push.return_value = test_upload_id # the second response, for telling the store it was pushed test_status_url = "https://store.c.c/status" client_mock.post.return_value = {"status-url": test_status_url} # the third response, status ok (note the patched UPLOAD_ENDING_STATUSES below) test_revision = 123 test_status_ok = "test-status" status_response = { "revisions": [{ "status": test_status_ok, "revision": test_revision, "errors": None }] } client_mock.get.return_value = status_response test_status_resolution = "test-ok-or-not" fake_statuses = {test_status_ok: test_status_resolution} test_filepath = "test-filepath" test_endpoint = "/v1/test/revisions/endpoint/" extra_fields = {"extra-key": "1", "more": "2"} with patch.dict("charmcraft.commands.store.store.UPLOAD_ENDING_STATUSES", fake_statuses): store._upload(test_endpoint, test_filepath, extra_fields=extra_fields) # check all client calls assert client_mock.mock_calls == [ call.push(test_filepath), call.post(test_endpoint, { "upload-id": test_upload_id, "extra-key": "1", "more": "2" }), call.get(test_status_url), ]
def test_upload_error(client_mock, config): """The upload ended in error.""" store = Store(config.charmhub) # the first response, for when pushing bytes test_upload_id = "test-upload-id" client_mock.push.return_value = test_upload_id # the second response, for telling the store it was pushed test_status_url = "https://store.c.c/status" client_mock.post.return_value = {"status-url": test_status_url} # the third response, status in error (note the patched UPLOAD_ENDING_STATUSES below) test_revision = 123 test_status_bad = "test-status" status_response = { "revisions": [{ "status": test_status_bad, "revision": test_revision, "errors": [ { "message": "error text 1", "code": "error-code-1" }, { "message": "error text 2", "code": "error-code-2" }, ], }] } client_mock.get.return_value = status_response test_status_resolution = "test-ok-or-not" fake_statuses = {test_status_bad: test_status_resolution} test_filepath = "test-filepath" with patch.dict("charmcraft.commands.store.store.UPLOAD_ENDING_STATUSES", fake_statuses): result = store._upload("/test/endpoint/", test_filepath) # check result assert result.ok == test_status_resolution assert result.status == test_status_bad assert result.revision == test_revision error1, error2 = result.errors assert error1.message == "error text 1" assert error1.code == "error-code-1" assert error2.message == "error text 2" assert error2.code == "error-code-2"
def test_upload_straightforward(client_mock, caplog, config): """The full and successful upload case.""" caplog.set_level(logging.DEBUG, logger="charmcraft.commands") store = Store(config.charmhub) # the first response, for when pushing bytes test_upload_id = "test-upload-id" client_mock.push.return_value = test_upload_id # the second response, for telling the store it was pushed test_status_url = "https://store.c.c/status" client_mock.post.return_value = {"status-url": test_status_url} # the third response, status ok (note the patched UPLOAD_ENDING_STATUSES below) test_revision = 123 test_status_ok = "test-status" status_response = { "revisions": [{ "status": test_status_ok, "revision": test_revision, "errors": None }] } client_mock.get.return_value = status_response test_status_resolution = "test-ok-or-not" fake_statuses = {test_status_ok: test_status_resolution} test_filepath = "test-filepath" test_endpoint = "/v1/test/revisions/endpoint/" with patch.dict("charmcraft.commands.store.store.UPLOAD_ENDING_STATUSES", fake_statuses): result = store._upload(test_endpoint, test_filepath) # check all client calls assert client_mock.mock_calls == [ call.push(test_filepath), call.post(test_endpoint, {"upload-id": test_upload_id}), call.get(test_status_url), ] # check result (build after patched ending struct) assert result.ok == test_status_resolution assert result.status == test_status_ok assert result.revision == test_revision # check logs expected = [ "Upload test-upload-id started, got status url https://store.c.c/status", "Status checked: " + str(status_response), ] assert expected == [rec.message for rec in caplog.records]
def test_upload_error(client_mock, config): """The upload ended in error.""" store = Store(config.charmhub) # the first response, for when pushing bytes test_upload_id = 'test-upload-id' client_mock.push.return_value = test_upload_id # the second response, for telling the store it was pushed test_status_url = 'https://store.c.c/status' client_mock.post.return_value = {'status-url': test_status_url} # the third response, status in error (note the patched UPLOAD_ENDING_STATUSES below) test_revision = 123 test_status_bad = 'test-status' status_response = { 'revisions': [{ 'status': test_status_bad, 'revision': test_revision, 'errors': [ { 'message': "error text 1", 'code': "error-code-1" }, { 'message': "error text 2", 'code': "error-code-2" }, ], }] } client_mock.get.return_value = status_response test_status_resolution = 'test-ok-or-not' fake_statuses = {test_status_bad: test_status_resolution} test_filepath = 'test-filepath' with patch.dict('charmcraft.commands.store.store.UPLOAD_ENDING_STATUSES', fake_statuses): result = store._upload('/test/endpoint/', test_filepath) # check result assert result.ok == test_status_resolution assert result.status == test_status_bad assert result.revision == test_revision error1, error2 = result.errors assert error1.message == "error text 1" assert error1.code == "error-code-1" assert error2.message == "error text 2" assert error2.code == "error-code-2"